「刷刷刷」169.多数元素

题目

难度:简单

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。

  • 进阶:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/majority-element

思路

进阶要求是找到时间复杂度 O(n)、空间复杂度为 O(1)的解法。比较容易想到的方法是使用哈希表记录元素出现的次数,再找最多的,复杂度不能满足进阶要求。

另外还有一个比较巧妙的方法是:给数组排序,1/2位置处的元素一定是众数。但也不满足进阶要求。

最优解应该是「摩尔投票法」:

如果把所有众数记为 1,其他数字都记为 -1。
因为众数是数组里出现最多的元素,所以全部相加之后的结果一定是大于 0 的。

代码实现上,每人一票来进行选举,变量 vote 记录的票数,所有人只会把票投给和自己一样的人。
我们先选出一个元素作为候选人,候选人会把自己的票投给自己。

然后遍历数组:

  • 如果下一位和候选人相同,则把票投给他,vote + 1
  • 如果不相同,则 vote - 1
  • 如果 vote 变为 0 ,则更换候选人为当前投票人继续选举

最终剩下的候选人成功当选,并且一定是人数整体占优的(众数)

也就是说,将众数元素看作一派,其他所有元素都看作一派,两边pk,一换一,最终一定至少能剩下一个众数元素。另外其他所有元素中还可以内斗,但结果只是让众数元素这一派的优势更大。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public int majorityElement(int[] nums) {

int target = nums[0];
int vote = 1;

for (int i = 1; i < nums.length; i++) {
if (nums[i] == target) {
vote++;
} else {
vote--;
}

if (vote == 0) {
vote = 1;
target = nums[i];
}
}

return target;
}
}

作者:prik
永久链接: https://trzoey.github.io/blog-prik/algorithmic/169.多数元素/
转载请注明出处,谢谢合作💓。