215. 数组中的第K个最大元素
在未排序的数组中找到第 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
说明:
你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。
思路一:排序后取值
复杂度分析:
时间复杂度:排序时间为O(nlogn),所以时间为O(nlogn)
空间复杂度:O(1)
思路二:利用堆
维持一个大小为K的最小堆,堆顶的元素始终是当前所有元素中第K大的元素
1 class Solution {
2 public int findKthLargest(int[] nums, int k) {
3 PriorityQueue<Integer> heap = new PriorityQueue<>(); // 最小堆
4 for(int i : nums){
5 heap.offer(i);
6 if(heap.size() > k){
7 heap.poll(); // 维持堆的大小为k
8 }
9 }
10 return heap.poll();
11 }
12 }
力扣测试时间为:6ms, 空间为40.2MB
复杂度分析:
时间复杂度:一个维持堆大小为k的过程,所以时间复杂度为O(Nlogk)
空间复杂度:O(k),也就是堆的大小
思路三:
借助快排的过程
1 class Solution {
2 public int findKthLargest(int[] nums, int k) {
3 // 借助快排的过程
4 return quickSort(nums, 0, nums.length - 1, nums.length - k);
5 }
6
7 public int partition(int[] nums, int left, int right){
8 // 选取第一个元素为主元
9 int pivot = nums[left];
10
11 while(left < right){
12 while(left < right && nums[right] >= pivot){
13 right--;
14 }
15 nums[left] = nums[right];
16
17 while(left < right && nums[left] <= pivot){
18 left++;
19 }
20 nums[right] = nums[left];
21 }
22 nums[left] = pivot;
23 return left;
24 }
25
26 public int quickSort(int[] nums, int left, int right, int k){
27 // 如果经过一轮快排分区后主元位置刚好是k,那么可以直接退出了
28 int mid = partition(nums, left, right);
29 if(mid == k){
30 return nums[k];
31 }else if(mid > k){
32 return quickSort(nums, left, mid - 1, k);
33 }else{
34 return quickSort(nums, mid + 1, right, k);
35 }
36 }
37 }
力扣测试时间为9ms, 空间为40.6MB
复杂度分析:
时间复杂度:每次将数组分成两段,只会选择其中一段进行partition操作,所以时间复杂度为O(N+N/2 + N/4 + 1) =
![](https://img-blog.csdnimg.cn/img_convert/a8045a066cd6372e257141cc9398d483.png)
空间复杂度为:O(1)