给定一个大小为 n
的数组 nums
,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋
的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入:nums = [3,2,3] 输出:3
示例 2:
输入:nums = [2,2,1,1,1,2,2] 输出:2
提示:
n == nums.length
1 <= n <= 5 * 104
-109 <= nums[i] <= 109
进阶:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。
摩尔投票法:
摩尔投票是一种用来解决绝对众数问题的算法。
在一个集合中,如果一个元素的出现次数比其他所有元素的出现次数之和还多,那么就称它为这个集合的绝对众数。等价地说,绝对众数的出现次数大于总元素数的一半。
摩尔投票算法的基本思想是维护一个候选众数和其出现的次数。遍历数组,当遇到与候选众数相同的数时,计数器加一,否则减一。当计数器归零时,更换候选众数。由于题目中明确给出多数元素一定存在,因此遍历完数组后,候选众数即为所求。
注意:
摩尔投票法解决的是绝对众数,不是众数。
例如:
C语言代码实现:
int majorityElement(int* nums, int numsSize) {
int candidate = nums[0];
int count = 1;
for (int i = 1; i < numsSize; i++) {
if (nums[i] == candidate) {
count++;
} else {
count--;
}
if (count == 0) {
candidate = nums[i];
count = 1;
}
}
return candidate;
}
如果计数为零,就选择新的候选人,因为前面的谁都不占优势了,后面出现谁就选谁。
具体参考大佬的文章:算法学习笔记(78): 摩尔投票 - 知乎 (zhihu.com)
如果要找N个数
int majorityElement(int* nums, int numsSize,const int N) {
int m[N], cnt[N];
memset(m, 0, sizeof(m));
memset(cnt, 0, sizeof(cnt));
for (int k = 0; k < numsSize; k++) {
int e = nums[k];
int i;
for (i = 0; i < N; i++) {
if (m[i] == e) {
cnt[i]++;
break;
}
}
if (i == N) {
int j;
for (j = 0; j < N; j++) {
if (cnt[j] == 0) {
m[j] = e;
cnt[j] = 1;
break;
}
}
if (j == N) {
for (int l = 0; l < N; l++) {
cnt[l]--;
}
}
}
}
// 最后需要验证答案是否符合要求
int majority = 0;
int maxCount = 0;
for (int i = 0; i < N; i++) {
if (cnt[i] > maxCount) {
maxCount = cnt[i];
majority = m[i];
}
}
return majority;
}