215. 数组中的第K个最大元素
题目描述
给定整数数组 nums
和整数 k
,请返回数组中第 k
个最大的元素。
请注意,你需要找的是数组排序后的第 k
个最大的元素,而不是第 k
个不同的元素。
你必须设计并实现时间复杂度为 O(n)
的算法解决此问题。
示例 1:
输入: [3,2,1,5,6,4],
k = 2
输出: 5
示例 2:
输入: [3,2,3,1,2,4,5,5,6],
k = 4
输出: 4
提示:
1 <= k <= nums.length <= 105
-104 <= nums[i] <= 104
方法一:快速选择
快速选择算法是一种在未排序的数组中查找第 k
个最大元素或最小元素的算法。它的基本思想是每次选择一个基准元素,将数组分为两部分,一部分的元素都比基准元素小,另一部分的元素都比基准元素大,然后根据基准元素的位置,决定继续在左边还是右边查找,直到找到第 k
个最大元素。
时间复杂度
java
class Solution {
private int[] nums;
private int k;
public int findKthLargest(int[] nums, int k) {
this.nums = nums;
this.k = nums.length - k;
return quickSort(0, nums.length - 1);
}
private int quickSort(int l, int r) {
if (l == r) {
return nums[l];
}
int i = l - 1, j = r + 1;
int x = nums[(l + r) >>> 1];
while (i < j) {
while (nums[++i] < x) {
}
while (nums[--j] > x) {
}
if (i < j) {
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
}
if (j < k) {
return quickSort(j + 1, r);
}
return quickSort(l, j);
}
}
cpp
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
int n = nums.size();
k = n - k;
auto quickSort = [&](auto&& quickSort, int l, int r) -> int {
if (l == r) {
return nums[l];
}
int i = l - 1, j = r + 1;
int x = nums[(l + r) >> 1];
while (i < j) {
while (nums[++i] < x) {
}
while (nums[--j] > x) {
}
if (i < j) {
swap(nums[i], nums[j]);
}
}
if (j < k) {
return quickSort(quickSort, j + 1, r);
}
return quickSort(quickSort, l, j);
};
return quickSort(quickSort, 0, n - 1);
}
};
ts
function findKthLargest(nums: number[], k: number): number {
const n = nums.length;
k = n - k;
const quickSort = (l: number, r: number): number => {
if (l === r) {
return nums[l];
}
let [i, j] = [l - 1, r + 1];
const x = nums[(l + r) >> 1];
while (i < j) {
while (nums[++i] < x);
while (nums[--j] > x);
if (i < j) {
[nums[i], nums[j]] = [nums[j], nums[i]];
}
}
if (j < k) {
return quickSort(j + 1, r);
}
return quickSort(l, j);
};
return quickSort(0, n - 1);
}
python
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
def quick_sort(l: int, r: int) -> int:
if l == r:
return nums[l]
i, j = l - 1, r + 1
x = nums[(l + r) >> 1]
while i < j:
while 1:
i += 1
if nums[i] >= x:
break
while 1:
j -= 1
if nums[j] <= x:
break
if i < j:
nums[i], nums[j] = nums[j], nums[i]
if j < k:
return quick_sort(j + 1, r)
return quick_sort(l, j)
n = len(nums)
k = n - k
return quick_sort(0, n - 1)
方法二:优先队列(小根堆)
我们可以维护一个大小为
时间复杂度
java
class Solution {
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> minQ = new PriorityQueue<>();
for (int x : nums) {
minQ.offer(x);
if (minQ.size() > k) {
minQ.poll();
}
}
return minQ.peek();
}
}
cpp
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int, vector<int>, greater<int>> minQ;
for (int x : nums) {
minQ.push(x);
if (minQ.size() > k) {
minQ.pop();
}
}
return minQ.top();
}
};
ts
function findKthLargest(nums: number[], k: number): number {
const minQ = new MinPriorityQueue();
for (const x of nums) {
minQ.enqueue(x);
if (minQ.size() > k) {
minQ.dequeue();
}
}
return minQ.front().element;
}
python
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
return nlargest(k, nums)[-1]
方法三:计数排序
我们可以使用计数排序的思想,统计数组
时间复杂度
java
class Solution {
public int findKthLargest(int[] nums, int k) {
Map<Integer, Integer> cnt = new HashMap<>(nums.length);
int m = Integer.MIN_VALUE;
for (int x : nums) {
m = Math.max(m, x);
cnt.merge(x, 1, Integer::sum);
}
for (int i = m;; --i) {
k -= cnt.getOrDefault(i, 0);
if (k <= 0) {
return i;
}
}
}
}
cpp
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
unordered_map<int, int> cnt;
int m = INT_MIN;
for (int x : nums) {
++cnt[x];
m = max(m, x);
}
for (int i = m;; --i) {
k -= cnt[i];
if (k <= 0) {
return i;
}
}
}
};
ts
function findKthLargest(nums: number[], k: number): number {
const cnt: Record<number, number> = {};
for (const x of nums) {
cnt[x] = (cnt[x] || 0) + 1;
}
const m = Math.max(...nums);
for (let i = m; ; --i) {
k -= cnt[i] || 0;
if (k <= 0) {
return i;
}
}
}
python
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
cnt = Counter(nums)
for i in count(max(cnt), -1):
k -= cnt[i]
if k <= 0:
return i