Leetcode 169题 Majority Element
Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.
You may assume that the array is non-empty and the majority element always exist in the array.
Example 1:
Input: [3,2,3]
Output: 3
Example 2:
Input: [2,2,1,1,1,2,2]
Output: 2
题目大意,求集合中出现次数最多的值,且此值出现次数大于总数的二分之一。 且次数一定存在。
这道题我在学习的时候给了我很多的启发。给了我在计算机思维上面有了很大的提点。求众数,随便一想,遍历、计数、返回。 觉得很简单,其实不然。
思路一:
最简单的思路,遍历、计数、返回值。 这里用到了哈希表。python中用字典表示。 字典的底层原理就是哈希表。
这里牵扯到.get的用法。 .get获取字典中某个键的值,若没有这个键返回None,若.get中添加值,则返回这个值。 字典中的计数频率高。
class Solution:
def majorityElement(self, nums: List[int]) -> int:
counts ={}
for i in nums:
counts[i] = counts.get(i,0)+1
#第一次计数肯定没有值,不能让其返回None,所以设置为0,再加1,则第一次统计为1.
if counts[i] > len(nums)/2:
return i
同理,这个应该归在方法一中。同样是计数。 利用集合中的.count方法,直接计数。 也挺方便。
操作过程中有一个问题。因为本来nums就被定义为List[int],所以本应该可以直接在nums中遍历循环,可以测试时通过,上交时却超时。 必须要先把nums取集合操作(set)之后,才能不超时,不知道为什么,还请大佬指导。对比代码如下
#测试通过,上交超时代码。
class Solution:
def majorityElement(self, nums: List[int]) -> int:
for i in nums:
if nums.count(i) > len(nums)/2:
return i
VS.
#取集合操作(set)代码。测试,上交均通过。
class Solution:
def majorityElement(self, nums: List[int]) -> int:
set_nums = set(nums)
for i in set_nums:
if nums.count(i) > len(nums)/2:
return i
思路二:
先把数字集合排序,因为要求的众数大于总数的二分之一且一定存在。所以最中间的那个数肯定是要求的众数。很巧妙!
上代码。
class Solution(object):
def majorityElement(self, nums):
nums.sort()
return nums[int(len(nums)/2)] #int取整。
实践过程中,如果数字集合有奇数个,还牵扯到取整的问题。
两个方法:1.四舍五入round()向上取整 2. int()向下取整。
因为数字集合从0开始计算,所以实际上int()向下取的整才是中间的值。
思路三:
随机抽一个数,判断它出现的次数是否大于二分之一。因为众数大于二分之一,所以理论上来说最多取两次。 最差则取一半加一的次数。理论效率比全部统计次数高,实际存在最差的情况。
class Solution(object):
def majorityElement(self, nums):
import random
while nums:
r = random.choice(nums)
if nums.count(r) > len(nums)/2:
return r
运行效率在数字集合大时得以体现。
思路三: 应该叫做摩尔投票(Moore Voting Algorithm)。
每次都找出一对不同的元素,从数组中删掉,直到数组为空或只有一种元素。 不难证明,如果存在元素e出现频率超过半数,那么数组中最后剩下的就只有e。
这个思路很巧妙,有点像异或用法,其实用了一个类似于异或的交换率,仔细想想就相同了。
上代码。
class Solution(object):
def majorityElement(self, nums):
major = count = 0
for i in nums:
if count == 0:
major = i
count = 1
else:
count += 1 if major==i else -1 #此处的= =做对比作用,不是赋值,否则就很容易迷。
return major
很巧妙!
其他的思路有点儿不太适合了,都有些为赋新词强说愁的感觉。
2020/03/25
写了三个思路,耗费了我两个小时的时间。心痛。
疫情中的英国,加油!