leetcode 169 多数元素
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例:
输入: [3,2,3]
输出: 3
输入: [2,2,1,1,1,2,2]
输出: 2
解题思路:
- 暴力法
写两个循环,第一个循环所有数,第二个循环计算这个数出现的次数,count>n/2返回,O(N^2) - Map法:{x : count_x} ,先计数,然后在字典中找count最大的且要count>n/2,O(N),空间也是O(N)
- sort法:对数组进行排序,然后从头去找,只要看到一个数出现了>n/2次,直接返回,O(NlogN)
- 分治:把数组分半,左右两边各自找count数最多的,如果是同一个值,那么返回,如果哪边的count比较多,就返回哪边. O(NlogN)
代码思路:
Map法:自己写的,也是比较简单。第二段是leetcode找到的
排序法:好简单- -
代码:
Map法:
class Solution:
def majorityElement(self, nums: List[int]) -> int:
a = dict()
for i in nums:
if i not in a:
a[i] = 1
else:
a[i]+=1
for i,v in a.items():
if v > len(nums)//2 :
return i
return None
class Solution:
def majorityElement(self, nums):
counts = collections.Counter(nums)
return max(counts.keys(), key=counts.get)
sort:
class Solution:
def majorityElement(self, nums):
nums.sort()
return nums[len(nums)//2]
分治法:
lass Solution:
def majorityElement(self, nums, lo=0, hi=None):
def majority_element_rec(lo, hi):
# base case; the only element in an array of size 1 is the majority
# element.
if lo == hi:
return nums[lo]
# recurse on left and right halves of this slice.
mid = (hi-lo)//2 + lo
left = majority_element_rec(lo, mid)
right = majority_element_rec(mid+1, hi)
# if the two halves agree on the majority element, return it.
if left == right:
return left
# otherwise, count each element and return the "winner".
left_count = sum(1 for i in range(lo, hi+1) if nums[i] == left)
right_count = sum(1 for i in range(lo, hi+1) if nums[i] == right)
return left if left_count > right_count else right
return majority_element_rec(0, len(nums)-1)
复 杂 度 分 析 : \color{red}{复杂度分析:} 复杂度分析:
进阶分析:
有一个摩尔投票法,思路是两个变量,候选人和计数,
遍历数组,把第一个数字放入候选人,计数+1,如果后面元素是同一个数字,那么计数+1,要不然计数-1,当发现count=0,候选人换成现在遍历的元素,然后重复操作,最后候选人是谁,那么就是答案
class Solution(object):
def majorityElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
major = 0
count = 0
for n in nums:
if count == 0:
major = n
if n == major:
count = count + 1
else:
count = count - 1
return major
时间复杂度:O(n),仅遍历一次数组
空间复杂度:O(1),没有使用额外空间