website/content.en/ChapterFour/0200~0299/0215.Kth-Largest-Element-in-an-Array.md
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
Example 1:
Input: [3,2,1,5,6,4] and k = 2
Output: 5
Example 2:
Input: [3,2,3,1,2,4,5,5,6] and k = 4
Output: 4
Note:
You may assume k is always valid, 1 ≤ k ≤ array's length.
Find the Kth largest element in an array. This problem is very classic. It can be implemented with O(n) time complexity.
package leetcode
import (
"math/rand"
"sort"
)
// Solution 1: Sorting; the sorting method is actually the fastest
func findKthLargest1(nums []int, k int) int {
sort.Ints(nums)
return nums[len(nums)-k]
}
// Solution 2: The theoretical basis of this method is that the index of the point obtained by partition is the index after the final sorting; based on this index, we can determine where the Kth largest number is
// Time complexity O(n), space complexity O(log n), worst-case time complexity O(n^2), space complexity O(n)
func findKthLargest(nums []int, k int) int {
m := len(nums) - k + 1 // mth smallest, from 1..len(nums)
return selectSmallest(nums, 0, len(nums)-1, m)
}
func selectSmallest(nums []int, l, r, i int) int {
if l >= r {
return nums[l]
}
q := partition(nums, l, r)
k := q - l + 1
if k == i {
return nums[q]
}
if i < k {
return selectSmallest(nums, l, q-1, i)
} else {
return selectSmallest(nums, q+1, r, i-k)
}
}
func partition(nums []int, l, r int) int {
k := l + rand.Intn(r-l+1) // This is an optimization, making the expected time complexity reduce to O(n), while the worst-case time complexity is O(n^2)
nums[k], nums[r] = nums[r], nums[k]
i := l - 1
// nums[l..i] <= nums[r]
// nums[i+1..j-1] > nums[r]
for j := l; j < r; j++ {
if nums[j] <= nums[r] {
i++
nums[i], nums[j] = nums[j], nums[i]
}
}
nums[i+1], nums[r] = nums[r], nums[i+1]
return i + 1
}
// Extension: Coding Interviews Offer 40. The smallest k numbers
func getLeastNumbers(arr []int, k int) []int {
return selectSmallest1(arr, 0, len(arr)-1, k)[:k]
}
// It is implemented exactly the same as selectSmallest; only the return value no longer needs to be sliced, and nums can be returned directly
func selectSmallest1(nums []int, l, r, i int) []int {
if l >= r {
return nums
}
q := partition(nums, l, r)
k := q - l + 1
if k == i {
return nums
}
if i < k {
return selectSmallest1(nums, l, q-1, i)
} else {
return selectSmallest1(nums, q+1, r, i-k)
}
}