• 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 };
  • 相关阅读:
    转:马云邮件全文
    XIFF资料1
    代码还是请一个字母一个字母敲(如果您只想混口饭吃就不要读了本文只面向想成为hacker的程序员)
    一个本来很有希望的项目噶然而止,脑子一下子空了
    转:进京感受一个技术人职业发展心得
    java中定义接口
    两个大数相乘(纯C实现)
    [ios学习入门1]hello,word!
    两台电脑通信的连接过程
    谁说引用不可改变
  • 原文地址:https://www.cnblogs.com/habibah-chang/p/14643795.html
Copyright © 2020-2023  润新知