leetcode第169题,这个题要求寻找数组中的多数元素,多数元素就是数量多于数组元素个数二分之一的元素,且题目说明数组非空且一定存在该元素。
第一种方法,哈希表,有一种数据结构记录每个数出现次数,最后排一下序,找出最大的,这个方法不仅适用于找多数元素,还可以找任意最多数目的元素。这里我使用了python的字典,使用了一些python特有的工具,字典排序,lambda表达式指定的是按键值排序还是按值排序,排序结果是一个带有键值对元组的列表。
class Solution(object):
def majorityElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
rec = {}
for num in nums:
if num in rec:
rec[num] += 1
else:
rec[num] = 1
nrec = sorted(rec.iteritems(),key=lambda d:d[1],reverse = True)
return nrec[0][0]
第二种方法,比较巧妙,先把数组排序,既然多数元素个数超过数组的一半,那么去中间值一定是多数元素。
class Solution(object):
def majorityElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
n = len(nums)
nums.sort()
return nums[n/2]
以上两种方法的复杂度都关系到排序的复杂度,最快是nlogn。还有一种方法是线性复杂度,思路是如果删去两个不同的元素,上下的元素中多数元素仍然是多数元素。这就是摩尔投票法。摩尔投票法基于这样一个原理,那就是如果成对消去不同的元素,最后剩余的元素一定是过半数的绝对多数元素。
class Solution:
# @param num, a list of integers
# @return an integer
def majorityElement(self, num):
currNum = -1
times = 0
for i in range(len(num)):
if (times == 0):
currNum = num[i]
times = 1
else:
if (num[i]==currNum):
times = times+1
else:
times = times-1
return currNum
依次扫描数组,并把当前元素值设置为候选元素,如果扫描过程中与候选元素相同,那么计数器自增,否则自减,自减就代表成对消去的过程。在扫描过程中还要不断检查计数器,如果计数器归零了,就说明当前已经成对消去了全部的候选,要有从新的数字开始作为候选了。
关于摩尔投票法,有一个很好的说明链接如下:
https://www.zhihu.com/question/49973163/answer/235921864