给定一个大小为 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
}