##题目
Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times.
Note: The algorithm should run in linear time and in O(1) space.
Example 1:
Input: [3,2,3]
Output: [3]
Example 2:
Input: [1,1,1,3,3,2,2,2]
Output: [1,2]
##题意
这道题是众数I的一个变形题,这里面是找出出现次数超过数组长度1/3的所有数。
##想法
这道题如果不考虑空间复杂度的话直接用字典做会非常直观好写,但这里是要求O(1)空间的。其实题目已经算是给出一些提示,个人认为在不涉及非常复杂的数据结构时其实有时候可以从问题限制里面找线索,因为如果问题描述中的限制往往可以倒推出一些有意思的东西。比如说这道题,其实提到的是超过1/3之一,也就是说一定会多于1/3。如果这样的数多于1/3,则意味着如果每次都消除三个不一样的数,最后目标就是在剩下来的数里面。而这样的目标数一定不会超过两个,简单反证法就能理解了。
这里需要注意的是上面说的是目标一定会在剩下来的数里面,剩下来的数不一定全是,举例两个例子:一种是如果只有两个数,[3,3,3,4]; 另外一种是[3,2,1,3,4];我们的消除只能是保证满足性质的不会被消掉,但剩下来的不一定都满足性质;
##实现
class Solution:
def majorityElement(self, nums: List[int]) -> List[int]:
if len(nums)==0:
return []
can1, cn1, can2, cn2 = 0, 0, 0, 0
for num in nums:
if num == can1:
cn1 += 1
elif num == can2:
cn2 += 1
elif cn1 == 0:
can1 = num
cn1 = 1
elif cn2 == 0:
can2 = num
cn2 = 1
else:
cn1 -= 1
cn2 -= 1
candidates = []
if cn1 != 0:
cn1 = 0
for num in nums:
if num == can1:
cn1 += 1
if cn1 > len(nums)//3:
candidates.append(can1)
if cn2 != 0:
cn2 = 0
for num in nums:
if num == can2:
cn2 += 1
if cn2 > len(nums)//3:
candidates.append(can2)
return candidates