「这是我参与11月更文挑战的第 3 天,活动详情查看:2021最后一次更文挑战」
寻找第K大
题目来源:LeetCode-1985. 找出数组中的第 K 大整数
题目描述
给你一个字符串数组 nums 和一个整数 k 。nums 中的每个字符串都表示一个不含前导零的整数。
返回 nums 中表示第 k 大整数的字符串
注意:重复的数字在统计时会视为不同元素考虑。例如,如果 nums 是 ["1","2","2"],那么 "2" 是最大的整数,"2" 是第二大的整数,"1" 是第三大的整数
示例
示例 1
输入:nums = ["3","6","7","10"], k = 4
输出:"3"
解释:nums 中的数字按非递减顺序排列为 ["3","6","7","10"],其中第 4 大整数是 "3"
示例 2
输入:nums = ["2","21","12","1"], k = 3
输出:"2"
解释:nums 中的数字按非递减顺序排列为 ["1","2","12","21"],其中第 3 大整数是 "2"
示例 3
输入:nums = ["0","0"], k = 2
输出:"0"
解释:nums 中的数字按非递减顺序排列为 ["0","0"],其中第 2 大整数是 "0"
提示:
- 1 <= k <= nums.length <= 104
- 1 <= nums[i].length <= 100
- nums[i] 仅由数字组成
- nums[i] 不含任何前导零
解题
解法一:快排思想
思路
跟上一篇文章中的求最小的k个数思路是一样的,这里直接说过程:
- 按照快排思想,找到一个分区点,将数组中大于该分区点元素的,放到分区点右边,小于的放左边
- 判断分区点的位置与k的大小关系,如果分区点位置大于k,则取分区点的左边部分数组,重复步骤1
- 如果分区点位置小于k,则取分区点的右边部分数组,重复步骤1
代码
func FindK(arr []int, k int) int {
if k == 0 {
return 0
}
return QuickSortK(arr, 0, len(arr)-1, k)
}
func QuickSortK(arr []int, start, end, k int) int {
for true {
if start > end {
return -1
}
pivot := partionK(arr, start, end)
if pivot == k {
return arr[k-1]
} else if pivot < k {
start = pivot + 1
} else {
end = pivot - 1
}
}
return -1
}
func partionK(arr []int, start, end int) int {
pivotValue := arr[end]
i := start
for j := start; j < len(arr); j++ {
if arr[j] > pivotValue {
arr[i], arr[j] = arr[j], arr[i]
i++
}
}
arr[end], arr[i] = arr[i], arr[end]
return i
}
解法二:大顶堆
思路
跟上一篇文章中的求最小的k个数思路是一样的,这里直接说过程(维护一个大小为K的小顶堆):
- 遍历数组中的每一个元素
- 将数组中的前K个数初始化成一个小顶堆
- 数组中的剩余元素和堆顶元素进行比较,如果大于堆顶元素,则替换堆顶元素,并堆化
- 元素遍历完之后,堆顶元素就是第K大的元素
代码
func HeapFinK(arr []int, k int) int {
if k == 0 {
return -1
}
length := len(arr)
maxK := make([]int, k+1)
for j := 0;j < k; j++ { //arr中的前k个复制到minK中
maxK[j+1] = arr[j]
}
for i:=k/2; i>0; i-- { // 堆化小顶堆
heapifyK(maxK, k+1, i)
}
for x := k; x < length; x ++ {
if arr[x] > maxK[1] { //如果当前元素大于堆顶元素
//移除堆顶元素(其实就是从堆中删除一个元素) 删除堆顶元素,然后将最后一个元素放到堆顶,然后再进行堆化
count := len(maxK)
maxK[1] = maxK[count-1]
count--
heapifyK(maxK, count, 1)
//将当前元素插入到堆中
count++
maxK[count-1] = arr[x]
m := count-1
for m/2 > 0 && maxK[m] < maxK[m/2] {
maxK[m], maxK[m/2] = maxK[m/2], maxK[m]
m = m/2
}
}
}
return maxK[1]
}
func heapifyK(a []int, n, i int) {
for true {
maxPos := i
if 2*i < n && a[i] > a[2*i] {
maxPos = 2*i
}
if 2*i+1 < n && a[maxPos] > a[2*i+1] {
maxPos = 2*i+1
}
if maxPos == i {
break
}
a[i], a[maxPos] = a[maxPos], a[i]
i = maxPos
}
}