找出数组中出现次数大于n/2、n/3,n/k的数

版权声明:前半生,不害怕;后半生,不后悔! https://blog.csdn.net/qq_14842117/article/details/89216438

1.找出数组中次数大于n/2的元素
说明:算法空间复杂度o(n),时间复杂度o(1)
数组中次数超过n/2的数最多1个,设置一个频率数,前一个数和后一个数相同,频率+1,
否则-1,只要有数频率超过数组长度一半,最终这个频率肯定大于0.

public static int solve2(int [] array) {
    	if(array == null || array.length == 0) return -1;
    	int temp = array[0],time = 0;
    	for(int i= 0;i<array.length;i++) {
    		if(array[i] == temp) time++;
    		else if(time <=0) {
    			temp = array[i];
    			time = 0;
    		}else {
    			time --;
    		}
    	}
    	 time = 0;
    	for(int i = 0;i<array.length;i++) {
    		if(temp == array[i]) time++;
    	}
    	if(time>array.length/2) return temp;
    	return -1;
    }

2.找出数组中出现次数超过n/3的数
超过n/2的数,最多2个,可以设置两个临时变量保存数组元素,两个频率变量

public static ArrayList solve(int [] array) {
    ArrayList<Integer> list = new ArrayList<Integer>();
    if(array == null ||array.length == 0) return null;
    int maj1 = array[0],maj2 = array[0];
    int count1 = 0,count2 = 0;
    int len = array.length;
    for(int i = 0;i<len;i++) {
    	if(array[i] == maj1) count1++;
    	else if(array[i] == maj2) count2++;
    	else if(count1<=0) {
    		count1 = 1;
    		maj1 = array[i];
    	}else if(count2<=0) {
    		count2 = 1;
    		maj2 = array[i];
    	}else {
    		--count1;
    		--count2;
    	}
    }
    count1 = count2 =0;
    for(int i =0;i<len;i++) {
    	if(array[i] == maj1) count1++;
    	if(array[i] == maj2) count2++;
    }
    if(count1>len/3) list.add(maj1);
    if(count2>len/3) list.add(maj2);
    return list;
    }

3.找出数组个数大于n/k的
大于n/k的最多也就是k-1个,所以map集合每当满k-1个的时候,如果,前后不相等,集合内所有的元素个数都要-1,为0的清除掉。

public static void solve3(int [] arr,int k) {
    	Map<Integer,Integer> map = new HashMap<>();
    	//首先找到k-1个不同的数,并记录他们出现的次数,继续向后遍历
    	//若下一个数map里有则将该数个数即value+1,否则map里数的个数都减1
    	//否则加入该数,次数记为1
    	for(int anArr:arr) {
    	 Integer value;
    	 if((value = map.get(anArr))!=null) {
    		 map.replace(anArr, value+1);
    	 }else {
    		 if(map.size() == k-1) {
    			 subtrackAll(map,k);
    		 }else {
    			 map.put(anArr,1);
    		 }
    	 }
      }
     //将map里所有数的个数即value都清0,因为map中的数并非都符合要求
    	map.keySet().forEach(integer->map.replace(integer, 0));
     //再次循环统计map里数字的真正个数
    	for(int num:arr) {
    		Integer val;
    		if((val = map.get(num))!= null) {
    			map.replace(num, val+1);
    		}
    	}
    	map.forEach((key,value)->{
    		if(value>arr.length/k) {
    			System.out.println(key+" ");
    		}
    	});
    }
	private static void subtrackAll(Map<Integer, Integer> map, int k) {
		List<Integer> list = new ArrayList();
	// 将map里全部数字的value值减1,减1后若value==0,则删除该键
		map.forEach((integer,integer2)->{
			if(integer2 == 1) {
				list.add(integer);
			}else map.replace(integer, integer2-1);
		});
		if(list.size()!=0) {
			for(Integer key:list) {
				map.remove(key);
			}
		}	
	}  

为什么最后还要验证一下,例如找大于n/2的数,数组为 2 2 2 3 3 3 最终temp为3但是显然3个数并没有大于n/2

猜你喜欢

转载自blog.csdn.net/qq_14842117/article/details/89216438