版权声明:前半生,不害怕;后半生,不后悔! 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