【剑指offer】数组中出现次数超过一半的数字

时间:2022-11-21 11:04:43

题目描述:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

 

学艺不精,参考他人思想如下:

思想一:当一个数字出现的次数是数组长度一半的时候,它一定在这个数组排序后的中间位置,所以我们先找到排好序的数组的中间位置对应的数字,再反过来计算这个数字出现的次数,看是否大于数组长度的一半。

public class Solution {
public int MoreThanHalfNum_Solution(int[] array) {
if(array.length == 0 || array == null){
return 0;
}
//Arrays.sort(array);
//冒泡排序
for (int i = 0; i < array.length; i++) {
for (int j = 1; j < array.length-i; j++) {
if(array[j-1]>array[j]){
int tmp;
tmp=array[j-1];
array[j-1]=array[j];
array[j]=tmp;
}
}
}
int mid = array[array.length/2];
int count = 0;
for (int i : array){

if (i == mid){
count++;
}
}
return count > array.length/2 ? mid : 0;
}

我当时就觉得自己可以放弃代码这条路了(然而男盆友却说他还有个更高效的做法,从入门到放弃...真叫人头秃????)

 

思想二:求出数组中最大数,然后声明一个额外的数组counts,数组大小为最大数+1,然后统计,每次counts[array[i]]++;判断counts[array[i]]++是否大于array长度一半,若是则返回array[i],不是则继续遍历。

但是我觉得这个方法并不太好,当数组中出现了特别大的数字,比如100000000时,那么count数组岂不会超级大,占空间超级多?

 

思想三:采用阵地攻守的思想: 第一个数字作为第一个士兵,守阵地;count = 1; 遇到相同元素,count++; 遇到不相同元素,即为敌人,同归于尽,count–;当遇到count为0的情况,又以新的i值作为守阵地的士兵,继续下去,到最后还留在阵地上的士兵,有可能是主元素。 再加一次循环,记录这个士兵的个数看是否大于数组一般即可。

这是一个我可能死活都想不出来的方法,但是复杂度也很良好,值得学习。