前言
一题三解,又学到了新知识,重点关注第三种----摩尔投票法。
题目描述
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例1:
输入:[3,2,3]
输出:3
示例2:
输入:[2,2,1,1,1,2,2]
输出:2
解法
解法一:如果将数组 nums 中的所有元素按照单调递增或单调递减的顺序排序,那么下标为 n/2 的元素(下标从 0 开始)一定是众数。
class Solution {
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length / 2];
}
}
解法二:遍历整个数组,记录每个数值出现的次数(利用HashMap,其中key为数值,value为出现次数);接着遍历HashMap中的每个Entry,寻找value值 > nums.length / 2 的key即可。
class Solution {
public int majorityElement(int[] nums) {
int res = 0;
Map<Integer,Integer> map = new HashMap<>();
for(int i = 0;i < nums.length;i++){
map.put(nums[i],map.getOrDefault(nums[i],0) + 1);
}
for(Map.Entry<Integer,Integer> entry : map.entrySet()){
if(map.get(entry.getKey()) > nums.length / 2){
res = entry.getKey();
}
}
return res;
}
}
解法三:摩尔投票法
算法步骤:
-
我们维护一个候选众数 candidate 和它出现的次数 count。初始时 candidate 可以为任意值,count 为 0;
-
我们遍历数组 nums 中的所有元素,对于每个元素 x,在判断 x 之前,如果 count 的值为 0,我们先将 x 的值赋予 candidate,随后我们判断 x:
如果 x 与 candidate 相等,那么计数器 count 的值增加 1;
如果 x 与 candidate 不等,那么计数器 count 的值减少 1。
-
在遍历完成后,candidate 即为整个数组的众数。
可以看出摩尔投票法的核心就是 对拼消耗,因为众数的个数大于 n/2 ,所以通过两两对拼后,最后一定会有一个幸存者!
class Solution {
public int majorityElement(int[] nums) {
int candinate = 0;
int counter = 0;
for(int i = 0;i < nums.length;i++){
if(counter == 0){
candinate = nums[i];
counter++;
}else if(nums[i] == candinate){
counter++;
}else{
counter--;
}
}
return candinate;
}
}
总结
该题目标数的个数大于 n/2 ,是本题解题的核心。