1. 问题描述:
给定一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n / 3 ⌋ 次的元素。进阶:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1)的算法解决此问题。
示例 1:
输入:[3,2,3]
输出:[3]
示例 2:
输入:nums = [1]
输出:[1]
示例 3:
输入:[1,1,1,3,3,2,2,2]
输出:[1,2]
提示:
1 <= nums.length <= 5 * 10 ^ 4
-10 ^ 9 <= nums[i] <= 10 ^ 9
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/majority-element-ii
2. 思路分析:
这道题目可以使用摩尔投票法的扩展进行求解,因为要求超过 ⌊ n / 3 ⌋ 次的元素,所以我们可以看成有2个仓库r1,r2,仓库元素的数目为c1,c2,摩尔投票法使用的是抵消的思想,遍历的元素与当前仓库中所有元素都不相等的时候那么所有仓库的元素数目都要减去1,如果与某个仓库中的元素相等的时候那么对应仓库的元素数目加1,如果仓库为空的时候那么可以将当前元素放入到仓库中,并且对应仓库的元素数目加1,最后遍历一下仓库中记录的元素(如果某个元素次数超过⌊ n / k ⌋那么它必然会存到某个仓库中,并且声明k - 2个仓库即可),统计一下nums中出现与仓库中元素相等的数目,最后判断一下元素的数目是否超过 n / k(这道题目的k = 3) ,如果满足那么说明当前元素是符合条件的。
3. 代码如下:
import collections
from typing import List
class Solution:
def majorityElement(self, nums: List[int]) -> List[int]:
# r1, r2分别表示两个仓库, c1, c2表示两个仓库对应的数目
r1, r2, c1, c2 = None, None, 0, 0
for i in range(len(nums)):
if c1 and nums[i] == r1:
c1 += 1
elif c2 and nums[i] == r2:
c2 += 1
elif c1 == 0:
r1 = nums[i]
c1 += 1
elif c2 == 0:
r2 = nums[i]
c2 += 1
else:
c1 -= 1
c2 -= 1
c1, c2 = 0, 0
for i in range(len(nums)):
if nums[i] == r1: c1 += 1
elif nums[i] == r2: c2 += 1
res = list()
n = len(nums)
if c1 > n // 3: res.append(r1)
if c2 > n // 3: res.append(r2)
return res