多数排序在leetcode只是一个简单题,但是衍生出来的多种解法却非常有意思
首先是最容易想到的hash和排序算法,接着是
随机化
从概率来讲一个随机挑选一个元素并验证都很大概率是众数
func majorityElementRandom(nums []int) int {n := len(nums)mc := n / 2for {candidate := nums[rand.Int63n(int64(n))]count := 0for _, num := range nums {if num == candidate {count++}if count > mc {return candidate}}}
}
分治法
分治法是基于数组的众数一定来自于左右子数组的众数之一,因此将数组递归分治最后聚合得到最终的数组多数
func majorityElement(nums []int) int {var f func(lo, hi int) intf = func(lo, hi int) int {// 如果仅有一个元素,那么该元素就是众数if lo == hi {return nums[lo]}// 递归数组左右边,找到左右众数mid := lo + (hi-lo)/2left := f(lo, mid)right := f(mid+1, hi)// 若左右众数相等,直接返回if left == right {return left}// 统计左右众数的个数var lc, rc intfor i := lo; i <= hi; i++ {switch nums[i] {case left:lc++case right:rc++}}// 比较个数,返回最终众数if lc > rc {return left}return right}return f(0, len(nums)-1)
}
Boyer-Moore
这是本题中最优雅的解法了。设众数+1,非众数-1,那么即使最开始选上的不是众数,由于众数是超过半数的,那么一定在某个众数,发生计数为0的情况,那么此时选上的数就是众数
func majorityElement(nums []int) int {var count, candidate intfor _, num := range nums {if count == 0 {candidate = num}if candidate == num {count++} else {count--}}return candidate
}
https://leetcode.cn/problems/majority-element/description/