1、描述
在未排序的数组中找到第k个最大的元素。请注意,你需要找的是数组排序后的第k个最大的元素,而不是第k个不同的元素
例1:输入:[3, 2, 1, 5, 6, 4] 和 k = 2
输出:5
例2:输入:[3, 2, 3, 1, 2, 4, 5, 5, 6] 和 k = 4
输出:4
2、算法
1)、排序
思想:先对数组进行排序,再返回倒数第 k 个元素
func findKthLargest(_ nums : [Int], _ k : Int)->Int{
/*
排序,取出第k个元素
*/
var nums = nums.sorted()
return nums[nums.count-k]
}
2)快速选择
思想:随机选择一个枢轴。
使用划分算法将枢轴放在数组中的合适位置 pos。将小于枢轴的元素移到左边,大于等于枢轴的元素移到右边。
比较 pos 和 N - k 以决定在哪边继续递归处理。
时间复杂度:O(NlogN)。
func findKthLargest(_ nums : [Int], _ k : Int)->Int{
/*
快速选择 O(NlogN)。
随机选择一个枢轴。
使用划分算法将枢轴放在数组中的合适位置 pos。将小于枢轴的元素移到左边,大于等于枢轴的元素移到右边。
比较 pos 和 N - k 以决定在哪边继续递归处理。
*/
var nums = nums
let size = nums.count
return quickselect(nums, 0, size-1, size-k)
}
private func partition(_ nums : inout [Int], _ left : Int, _ right : Int, _ pivot_index : Int)->Int{
let pivot = nums[pivot_index]
//将基准元素移到末尾
nums.swapAt(pivot_index, right)
var store_index = left
//将左右小于基准的元素移到左边
for i in left...right{
if nums[i] < pivot{
nums.swapAt(store_index, i)
store_index += 1
}
}
//将基准移到最后
nums.swapAt(store_index, right)
return store_index
}
private func quickselect(_ nums : [Int], _ left : Int, _ right : Int, _ k_smallest :Int)->Int{
var nums = nums
//返回第k个最小的元素
//如果只有一个元素
if left == right{
return nums[left]
}
//选择一个随机的基准下标
var pivot_index = left+Int.randomIntNumber(Range(0...(right-left)))
pivot_index = partition(&nums, left, right, pivot_index)
//如果第k个最大值等于基准下标
if k_smallest == pivot_index {
return nums[k_smallest]
}else if k_smallest < pivot_index{
//基准左边查找
return quickselect(nums, left, pivot_index-1, k_smallest)
}else{
//基准右边查找
return quickselect(nums, pivot_index+1, right, k_smallest)
}
}