找出数组中出现次数超过一半的数字
数组中有一个数字出现次数超过数组长度的一半,请找出这个数字?(找出“水王”数)
1.第一种方法:
可以使用map进行映射,key值为数字,value值是这个数字在数组中出现的次数。
具体代码如下:
package testCoding; import java.util.*; public class Main{ public static void main(String[] args){ int[] array = {2,5,6,2,2,4,1,2,2,2};//假设数组中有10个数 int len = array.length; //利用一个map集合进行映射 Map<Integer,Integer> map = new HashMap<>(); for(int i=0;i<array.length;i++){ if(map.containsKey(array[i])){ map.put(array[i],map.get(array[i])+1); } else{ map.put(array[i],1); } } //遍历map集合,看哪一个数字的次数超过了数组长度的一半 for(Integer integer:map.keySet()){ if(map.get(integer)>len/2){ System.out.println("水王数:"+integer); return ; } } System.out.println("没有水王数!"); } }
2.第二种方法
利用“血量num”和“候选值candidate”来进行标记,遍历整个数组,依次比较,如果不一样就进行消去,一样的话就保留。以数组array = {2,5,6,2,2,4,1,2,2,2}为例:
最开始的时候:num=0; candidate=-1;(血量为0,无候选)(其实血量也就是候选里的个数)
从头开始遍历:
(1) 2 ----> num=1; candidate=2;
(2) 5 ----->num=0;candidate=-1;
(3) 6 ----->num=1;candidate=6;
(4) 2 ------>num=0;candidate=-1;
(5) 2 ----->num=1;candidate=2;
(6) 4 ----->num=0;candidate=-1;
(7) 1 ------>num=1;candidate=1;
(8) 2 ------>num=0;candidate=-1;
(9) 2 ----->num=1;candidate=2;
(10)2 ----->num=2;candidate=2;
但是要确定候选数到底是不是水王数,还需要再遍历一遍数组,看候选数出现的次数是不是整个数组的一半以上,这里最后剩下来的候选数2就是水王数。
考虑array={1,2,3,4,5},最后剩下候选数为5,但是5并不是水王数,所以需要再遍历一遍数组进行判断。
具体代码如下:
public class Main{ public static void main(String[] args){ int[] array = {2,5,6,2,2,4,1,9,2,2};//假设数组中有10个数 int len = array.length; //设置血量和候选值的初始值 int num=0,candidate=-1; //第一次遍历整个数组,计算得到最终血量以及候选值 for(int i=0;i<len;i++){ //如果血量为0,就将当前值设置为候选 if(num==0){ num++; candidate=array[i]; } //如果血量大于0,就将当前值与候选值进行比较 else if(candidate==array[i]) num++; else num--; } //判断留下来的候选值是不是水王数 if(num<=0){ System.out.println("没有水王数!"); return; } int n=0; for(int i=0;i<len;i++){ if(array[i] == candidate) n++; } if(n>len/2) System.out.println("水王数:"+candidate); else System.out.println("没有水王数!"); } }