给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
解决方案:一次删掉不同的数,最后如果有多数的话,他会剩下来,反过来不成立
如果不确定是否有多数,那么最后剩下来的数不一定就是多数
public int test(int[] nums){
int HP=0;//血量
int candidate=0;//候选人
for (int num:nums) {
//当血量为0时,此时的候选人就是该变量
if(HP==0){
candidate=num;
HP=1;
}else if(num!=candidate){//如果有候选,当此时的变量和候选人相同时,血量加1;
HP--;
}else{//不一样则减1
HP++;
}
}
//如果到最后没有候选人
if (HP==0){
return -1;
}
//如果到最后有候选人,则再遍历一遍,看该数在数组中共出现了几次
int count=0;
for (int num:nums) {
if (num==candidate){
count++;
}
}
int n=nums.length;
return count>(n>>1)?candidate:-1;
}
此方法也叫做摩尔投票法
由此可以的延伸出一到实际问题
美国投票选总统,有很多人来参加,只有当某个人得到了大于全国人的一半以上时才可以当选,每个人都用信封写的某个人,但是我们不知道,此时我们有个机器,他可以识别两个信封里面写的人一样不一样,此时就可以用这个多数问题来解决。
众数问题
给定一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素
public List<Integer> majorityElement(int[] nums) {
//定义一个list,最后将众数放入到list中,
List list=new ArrayList();
//因为要的终须需要超过n/3,所以最多有两个众数,最少一个也没有
int candidate1=nums[0];
int candidate2=nums[0];
int HP1=0,HP2=0;
for (int num:nums) {
//candidate1和candidate2是同一个值,但是第一次循环时,走的是这一个
if(candidate1==num){
HP1++;
continue;
}
if(candidate2==num){
HP2++;
continue;
}
//当遇到第一个不等同candidate1(candidate2)时,不走这一个,因为此时HP1不等于0,而是等于1
if(HP1==0){
candidate1=num;
HP1++;
continue;
}
//第一次遇到不等于candidate1(candidate2)的数是走的是这一个
if(HP2==0){
candidate2=num;
HP2++;
continue;
}
//当都不等于candidate1和candidate2时,HP1和HP2的血同时减一
HP1--;
HP2--;
}
//计数阶段,找到了两个候选人之后,需要确定票数是否满足大于 N/3
HP1=0;
HP2=0;
for(int num:nums){
if(num==candidate1){
HP1++;
}else if(num==candidate2){
HP2++;
}
}
int n=nums.length;
if(HP1>n/3) list.add(candidate1);
if(HP2>n/3) list.add(candidate2);
return list;
}