Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一、题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 输出: 2
限制:
1 <= 数组长度 <= 50000
二、思路分析
- 第一个想法是使用哈希表,表中存储所有数字,值则用来计数,如果计数数值超过nums长度的一半,则直接返回该数字。
- 使用哈希表,时间复杂度为O(n),空间复杂度为O(n)。
- 第二种方式是摩尔投票法,使用一个候选人变量和计数变量,候选人变量初始可以为任意值,遍历nums数组,如果计数变量为0则将候选人替换为当前遍历的num,如果当前遍历的num和候选人是同一个数字,则计数值+1,如果不是同一个数字则计数值-1,如果cnt为0则换候选人。
- 超过半数的数字,必然会换成候选人,并且cnt大于0。
- 摩尔投票法的空间复杂度为常数,且时间复杂度为O(n),优于哈希表法。
三、AC 代码
//哈希表法
func majorityElement(nums []int) int {
m := make(map[int]int,0)
for i := range nums {
m[nums[i]]++
}
for k,v := range m {
if v > len(nums)/2 {
return k
}
}
return nums[0]
}
//摩尔投票法
func majorityElement(nums []int) int {
candidate,cnt := 0,0
for _,num := range nums {
if cnt == 0 {
candidate = num
}
if candidate == num {
cnt++
}else{
cnt--
}
}
return candidate
}
四、总结
摩尔投票法,可以常数级别选举出众数。