215. Kth Largest Element in an Array

问题:

求数组中第k大的元素。

Example 1:
Input: nums = [3,2,1,5,6,4], k = 2
Output: 5

Example 2:
Input: nums = [3,2,3,1,2,4,5,5,6], k = 4
Output: 4
 

Constraints:
1 <= k <= nums.length <= 10^4
-10^4 <= nums[i] <= 10^4

  

解法:priority_queue(优先队列,堆heap),quick sort(快速查找)+ binary search(二分查找)

解法一:priority_queue

建立元素总数==k的最小堆,堆顶元素为最小元素。

那么堆顶即为所求。

将数组元素依次入堆,当堆size超过k,则弹出最小元素。(不断淘汰,第k+1大的元素,一定不为所求)

 

代码参考:

 1 class Solution {
 2 public:
 3     int findKthLargest(vector<int>& nums, int k) {
 4         priority_queue<int, vector<int>, greater<int>> q;//minimal heap: top->minimal element
 5         for(int n:nums) {
 6             q.push(n);
 7             if(q.size()>k) q.pop();
 8         }
 9         return q.top();
10     }
11 };

 

解法二:quick sort + binary search

  • 快速排序的方法:
    • 每次以第一个元素为标准,将小于标准的数放左边,大于标准的数放右边。
    • 最后将标准元素放中间。(标准元素的位置:即是最终排序好的位置,固定)

因此我们每次排序后,求标准元素位置p==size-k?(从小到大排序,从后往前第k个元素的index)

  • 如果是,则找到搜求。
  • 若p>size-k:
    • 那么,所求一定在p左边:接下来继续对 left~p-1 的元素进行快速排序。
  • 若p<size-k:
    • 那么,所求一定在p右边:接下来继续对 p+1~right 的元素进行快速排序。

 

♻️ 优化:由于快速排序依赖数组中 标准 的分布性,

为了防止极端情况,我们使用shuffle将数组打乱。

 

代码参考:

 1 class Solution {
 2 public:
 3     int findKthLargest(vector<int>& nums, int k) {
 4         int l=0,r=nums.size()-1;
 5         shuffle(nums);
 6         k=nums.size()-k;
 7         while(l<=r) {
 8             int p=partition(nums, l, r);
 9             if(p<k) {
10                 l=p+1;
11             } else if(p>k) {
12                 r=p-1;
13             } else {
14                 return nums[p];
15             }
16         }
17         return -1;
18     }
19     int partition(vector<int>& nums, int l, int r) {
20         if(l==r) return l;
21         int pivot=nums[l];
22         int i=l+1, j=r;
23         while(i<=j) {
24             if(nums[i]>pivot && nums[j]<pivot) {
25                 swap(nums[i], nums[j]);
26                 i++;
27                 j--;
28             } else {
29                 if(nums[i]<=pivot) i++;
30                 if(nums[j]>=pivot) j--;
31             }
32         }
33         swap(nums[l], nums[j]);//j can reach l+1
34         return j;
35     }
36     void shuffle(vector<int>& nums) {
37         int n=nums.size();
38         for(int i=0; i<n; i++) {
39             int k = i+rand()%(n-i);
40             swap(nums[i], nums[k]);
41         }
42         return;
43     }
44 };

 

posted @ 2021-04-11 14:36  habibah_chang  阅读(30)  评论(0编辑  收藏  举报