剑指Offer|数组中出现次数超过一半的数字

139 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例 1:

输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 输出: 2

限制:

1 <= 数组长度 <= 50000

二、思路分析

  1. 第一个想法是使用哈希表,表中存储所有数字,值则用来计数,如果计数数值超过nums长度的一半,则直接返回该数字。
  2. 使用哈希表,时间复杂度为O(n),空间复杂度为O(n)。
  3. 第二种方式是摩尔投票法,使用一个候选人变量和计数变量,候选人变量初始可以为任意值,遍历nums数组,如果计数变量为0则将候选人替换为当前遍历的num,如果当前遍历的num和候选人是同一个数字,则计数值+1,如果不是同一个数字则计数值-1,如果cnt为0则换候选人。
  4. 超过半数的数字,必然会换成候选人,并且cnt大于0。
  5. 摩尔投票法的空间复杂度为常数,且时间复杂度为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
}

四、总结

摩尔投票法,可以常数级别选举出众数。