题目来源
题目描述
题目解析
摩根投票法
候选人(major)初始化为num[0],票数count初始化为1
当遇到与major相同的数,则票数count = count + 1,否则count = count - 1;
当遇到count == 0时,更好候选人major,并将票数count重置为1
- cpp:
class Solution {
public:
int majorityElement(vector<int>& nums) {
int major = nums[0];
int count = 1;
for (int i = 1; i < nums.size(); ++i) {
if(count == 0){
major = nums[i];
count = 1;
}else{
if(nums[i] == major){
count++;
}else{
count--;
}
}
}
return major;
}
};
投票算法证明:
- 如果候选人不是maj 则 maj,会和其他非候选人一起反对 会反对候选人,所以候选人一定会下台(maj==0时发生换届选举)
- 如果候选人是maj , 则maj 会支持自己,其他候选人会反对,同样因为maj 票数超过一半,所以maj 一定会成功当选
排序
- 由于众数出现的频率大于n/2,所以在排序之后众数必存在于下标[n/2]处(本题默认数组中是一定存在众数的,所以返回下标[n/2]可行)
int majorityElement(vector<int>& nums) {
sort(nums.begin(), nums.end());
return nums[nums.size() / 2];
}
哈希表
使用hash映射来存储每个元素以及出现的次数。对于哈希映射中的每个键值对,键表示一个元素,值表示该元素出现的次数。
我们同样也可以在遍历数组 nums 时候使用打擂台的方法,维护最大的值,这样省去了最后对哈希映射的遍历。
class Solution {
public:
#include <unordered_map>
int majorityElement(vector<int>& nums) {
std::unordered_map<int, int> counts;
int majority = 0, count = 0;
for(int num : nums){
++counts[num];
if(counts[num] > count){
majority = num;
count = counts[num];
}
}
return majority;
}
};
随机法
class Solution {
// 生成一个随机坐标
private static int randomIndex(Random rand, int low, int high){
return rand.nextInt(high - low) + low;
}
// 统计当前元素出现的次数
public static int countElement(int[] arr, int index){
int count = 0;
for (int i = 0; i < arr.length; i++){
if (arr[i] == arr[index]){
count++;
}
}
return count;
}
public int majorityElement(int[] nums) {
Random rand = new Random();
int m = nums.length / 2;
while (true){
int index = randomIndex(rand, 0, nums.length);
int count = countElement(nums, index);
if (count > m){
return nums[index];
}
}
}
}
类似题目
题目 | 思路 |
---|---|
leetcode:169. 无序数组中的多数元素(超过n/2) majority-element | 这里已经确保了主要元素一定存在,所以最后不需要验证 |
面试题 17.10. 无序数组中的主要元素(超过n/2) find-majority-element-lcci | 没有说主要元素一定存在,所以最后需要看major是否是主要元素 |
leetcode:229. 无序数组中的多数元素 II(超过n/3) majority-element ii | |
leetcode:1287. 有序数组中出现次数超过25%的元素 |