地址
题目
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
思路
1.中位数思想
满足题目要求的数组经排序后,中间元素一定是结果,所以最简单的方法就是对数组进行排序,然后获取中间元素。因为这个题的用例有点问题,里面还有不满足这种要求的数组,所以获得结果后需要遍历数组进行验证。时间复杂度O(NlogN)
import java.util.Arrays;
public class Solution {
public int MoreThanHalfNum_Solution(int [] a) {
if(a == null || a.length == 0) return 0;
//排序
Arrays.sort(a);
//如果存在这个数,那么这个数一定在正中间
int res = a[a.length/2];
//因为测试用例有可能会有不存在的,所以需要验证
int count = 0;
for(int i : a){
if(i == res)
count++;
}
return count > a.length / 2?res:0;
}
}
2.计数法
当然了,第一种方法不是最优解,因为使用了排序。根据题目要求已知,如果满足要求的结果在数组中的个数一定比其他元素的个数总和多,所以我们可以设立两个变量,一个用于计数,一个用于储存当前元素。从第二个元素开始逐个比较,如果前一个元素等于当前元素,则计数器加1,否则计数器减1。如果计数器为0,则重新给两个变量赋值:计数器设置为1,当前变量储存,最后的结果一定是满足要求的元素。时间复杂度:O(N)。
public class Solution {
public int MoreThanHalfNum_Solution(int [] a) {
if(a == null || a.length == 0) return 0;
int count = 1;
int res = a[0];
for(int i = 1;i < a.length;i++){
if(count == 0){
//换成当前数
res = a[i];
count = 1;
}
if(res != a[i]){
count--;
}else{
count++;
}
}
//因为测试用例有可能会有不存在的,所以需要验证
count = 0;
for(int i : a){
if(i == res)
count++;
}
return count > a.length / 2?res:0;
}
}