169. 多数元素

78 阅读2分钟

169. 多数元素

给定一个大小为 n **的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

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

哈希

用哈希表存数字出现的次数

func majorityElement(nums []int) int {
   mp := make(map[int]int)
   n := len(nums)
   for _, v := range nums {
      mp[v]++
      if mp[v]*2 >= n {
         return v
      }
   }
   return 0
}

排序

当数组有序,那么超过n/2的哪个数字一定在 n/2处,可以把 众数看成一个窗口模拟滑动一下,一定会有一个值在中间

func majorityElement(nums []int) int {
   sort.Ints(nums)
   return nums[len(nums)/2]
}

摩尔投票算法

思路其实和哈希是一个意思,可以理解为兑子或者守擂,一个众数和一个非众数互兑,剩下的棋子一定是众数

可以用 ans记录擂主,num记录棋子出现数量

如果遍历的时候和旗子的值相同,num+1,不同就num - 1。ans是0就换擂主,最后剩下的就是众数

func majorityElement(nums []int) int {
   ans := 0
   num := 0
   for _, v := range nums {
      if num == 0 {
         ans = v
         num++
      } else if ans == v {
         num++
      } else {
         num--
      }
   }
   return ans
}

分治

分治的思想就是把大问题切割成小问题。

分治可以分为三步:

划分:二分

求解:每次分割的小数组求出一个最多元素。

合并:这些小数组的最多元素会合并成一个数组,再求出这个数组的最多元素

看到的题解,分析的很棒

func majorityElement(nums []int) int {
   return getMaxElement(nums, 0, len(nums)-1)
}

func getMaxElement(nums []int, l int, r int) int {
   if l == r {
      return nums[l]
   }
   mid := (r-l)/2 + l
   leftMaxElement := getMaxElement(nums, l, mid)
   rightMaxElement := getMaxElement(nums, mid+1, r)
   if leftMaxElement == rightMaxElement {
      return leftMaxElement
   }
   leftCnt := getCnt(nums, leftMaxElement, l, r)
   rightCnt := getCnt(nums, rightMaxElement, l, r)
   if leftCnt > rightCnt {
      return leftMaxElement
   }
   return rightMaxElement

}

func getCnt(nums []int, element int, l int, r int) int {
   num := 0

   for l <= r {
      if nums[l] == element {
         num++
      }
      l++
   }
   return num
}