1、描述
给定一个大小为n的数组,找到其中的众数。
众数是指在数组中出现次数大于 的元素。
你可以假设数组是非空的,并且给定的数组总是存在众数。
例1:输入:[3, 2, 3]
输出:3
例2:输入:[2, 2, 1, 1, 1, 2, 2]
输出:2
2、算法
1)哈希表
思想:利用字典存储每个数字出现的次数,最后取出每个数字的字数与 比较,次数大于它的即为众数
时间复杂度:O(n)
func majorityElement(_ nums : [Int])->Int{
/*
哈希表
*/
if nums.count == 0{
return 0
}
let count = nums.count / 2
var dic : [Int:Int] = [Int:Int]()
for num in nums {
if dic[num] == nil {
dic[num] = 1
}else{
dic[num] = dic[num]! + 1
}
}
for (key, value) in dic {
if value > count{
return key
}else{
return 0
}
}
return 0
}
2)排序
思想:
如果所有数字被单调递增或者单调递减的顺序排了序,那么众数的下标为[n/2](当n 是偶数时,下标为[n/2]+1
时间复杂度:O(nlogn)
func majorityElement(_ nums : [Int])->Int{
/*
排序
*/
if nums.count == 0{
return 0
}
let nums = nums.sorted()
return nums[nums.count/2]
}
3)分治
思想:
如果我们知道数组左边一半和右边一半的众数,我们就可以用线性时间知道全局的众数是哪个。
使用经典的分治算法递归求解,直到所有的子问题都是长度为 1 的数组
时间复杂度:O(nlogn)
func majorityElement(_ nums : [Int])->Int{
/*
分治
*/
return majorityElement(nums, 0, nums.count-1)
}
private func majorityElement(_ nums : [Int], _ lo : Int, _ hi : Int)->Int{
//如果数组只有一个元素
if lo == hi{
return nums[lo]
}
//递归求解左右两边的众数
let mid = (hi-lo)/2 + lo
var left = majorityElement(nums, lo, mid)
var right = majorityElement(nums, mid+1, hi)
if left == right {
return left
}
//比较左右两边众数的次数,找出最大次数的即为数组的众数
let leftCount = countInRange(nums, left, lo, hi)
let rightCount = countInRange(nums, right, lo, hi)
return leftCount > rightCount ? left : right
}
private func countInRange(_ nums : [Int], _ num : Int, _ lo : Int, _ hi : Int)->Int{
var count = 0
for i in lo...hi {
if nums[i] == num{
count += 1
}
}
return count
}