题目:给定一个大小为n的数组,找到其中的多数元素,多数元素是指在数组中出现次数大于n/2 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
实例1:
输入:[3,2,3]
输出:3
实例2:
输入:[2,2,1,1,1,2,2]
输出:2
看到这个题目,我第一反应想到的就是通过哈希表的映射关系来做,所以通过创建字典进行元素与个数的对应关系,从而实现多数元素的返回
在这里插入代码片
class Solution:
def majorityElement(self, nums: List[int]) -> int:
dic = {}
for i in set(nums):
dic[i] = nums.count(i)
return max(dic,key=dic.get)
之后去看了官方的题解,其中提到了一个Boyer-Moore投票算法,感觉之前没看到过,所以在此总结一下。
Boyer-Moore投票算法的详细步骤:
1、首先初始化一个候选众数candidate以及它的次数count。candidate可以是任意值,count为0
2、然后遍历整个数组中的元素,对于每个元素x,在判断x之前如果count的值为0,那么将x赋值予candidate,随后判断x:
(1)如果x和candidate相等,那么count的值加1
(2)如果x和candidate不相等,则count的值减1
3、遍历完成后,candidate即为整个数组的众数
个人理解:用大白话来说就是,从整个列表中一次遍历,先将第一个值当成众数,然后遇到相同的值,那么就投自己一票,即count加1,遇到了不相同的数值肯定不会投给起初的值,肯定也是投给它自己,那么就相当于与在原来的count基础上减1票,当count等于0时,相当于,起初认为的众数和另一个数的数量一样了,需要重新选举出来一个众数,所以当count等于0时,重新安排下一个数作为当前众数,最后剩下的肯定是数量最多的数字。
例子:[1,1,2,2,1,3,1]
(注意:题目中提到给定的数组总是存在多数元素,即众数>n/2,所以不存在[1,2,1,2]这种类似的情况)
1、起初令candidate=None(任意值),count=0
2、开始遍历数组,取第一个值1,判断count是否为0,为0则所以将1赋值给candidate,此时就相当于第一个数投了自己一票,所以count=0+1=1
3、随后继续遍历,第二个值依然等于1,此时count=1,所以不需要重新选举,则1还会投自己一票,所以count=1+1=2,当前的candidate=1不变
4、遍历到第一个2元素时,由于2不属于1的“帮派”,所以2会投自己一票,也就相当于减了1“帮派“一票,所以此时的count=2-1=1,candidate不变仍为1
5、当遇到第二个2时,此时再减1票,count=0,candidate=1,此时count=0,即代表下一次又要重新任命新的“众数”
6、此时又遇到1,判断count=0,所以将1重新任命为新的“众数”,即candidate=1,就相当于1投了自己一票,所以count=0+1=1
7、下一个元素为3,3反对1的任命,会减1一票,所以此时count=1-1=0,此时candidate仍为1,但是发现count=0了,所以下一次又将重新任命新的“众数”
8、最后一个元素等于1,此时由上一步知count=0,所以将1赋给candidate,故candidate=1,1上台,投自己一票,所以count=1(这里就可以理解为,4个1,2个2,1个3,4个1投了1一共4票,其他的不是1的反对了3票,所以最后1还有一票)
9、返回最后的candidate,即1
最后附上代码
在这里插入代码片
class Solution:
def majorityElement(self,nums):
count = 0
candidate = None
for num in nums:
if count == 0:
candidate = num
count += (1 if num == candidate else -1)
return candidate