• 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

    思路一:优先队列(小根堆)

    【c++】STL里的priority_queue用法总结_小拳头的博客-CSDN博客_priority_queue头文件

    priority_queue,greater> p;

    优先队列默认为大根堆,priority_queue p等于priority_queue,less> p

    时间复杂度:小根堆的插入删除时间复杂度为O(logN),for循环遍历整个数组,所以时间复杂度为O(NlogN),是不满足题意O(N),不过可以提交通过。

    1. class Solution {
    2. public:
    3. int findKthLargest(vector<int>& nums, int k)
    4. {
    5. priority_queue<int,vector<int>,greater<int>> p;
    6. for(int i=0;isize();i++)//所有元素都进一次小根堆
    7. {
    8. p.push(nums[i]);
    9. if(i>=k)//如果元素个数大于等于k,就把小根堆的堆顶元素(最小值)出出去
    10. {
    11. p.pop();
    12. }
    13. }
    14. int res=p.top();//此时小根堆有k个元素,堆顶的元素就是第k个最大的元素
    15. return res;
    16. }
    17. };

    思路二:快速选择算法(循环,不是递归)

    快速选择算法是快速排序的变体。第 k 个最大的元素,相当于数组升序排序的下标为 n - k 的元素(第n-k+1个元素)。

    在快速排序算法 partition 函数执行时,会将 nums[p] 排到正确的位置,使得 nums[low..p-1] < nums[p] < nums[p+1..high],此时就知道 nums[p] 的排名了。

    那么我们可以把 p 和 n-k 进行比较,如果 p < n-k 说明要找的元素在 nums[p+1..high] 中,如果 p > n-k 说明要找的元素在 nums[low..p-1] 中

    然后,去 nums[p+1..high] 或者 nums[lo..p-1] 这两个子数组中执行 partition 函数,就可以进一步缩小范围,最终找到目标元素。

    时间复杂度:O(N),不断循环,缩小范围,找到第k个最大的元素。

    1. class Solution
    2. {
    3. public:
    4. int findKthLargest(vector<int>& nums, int k)
    5. {
    6. srand(time(NULL));//设置随机种子
    7. random_shuffle(nums.begin(),nums.end());//使用random_shuffle需要先设置随机种子
    8. int n = nums.size();
    9. int low = 0;
    10. int high = n - 1;
    11. while (low<=high)//不断缩小范围
    12. {
    13. int p = partition(nums,low,high);
    14. if (p == n-k)
    15. return nums[p];
    16. else if (p < n-k)
    17. low = p + 1;
    18. else
    19. high = p - 1;
    20. }
    21. return -1;
    22. }
    23. //----左右交换
    24. int partition(vector<int> & nums, int low, int high)//同快速排序的partition函数
    25. {
    26. int pivot = nums[low];
    27. int i=low+1;
    28. int j=high;
    29. while (i<=j)
    30. {
    31. while(i
    32. i++;
    33. while(j>low&&nums[j]>=pivot)
    34. j--;
    35. if(i>=j)
    36. break;
    37. swap(nums[i], nums[j]);
    38. }
    39. swap(nums[low], nums[j]);
    40. return j;
    41. }
    42. };

  • 相关阅读:
    【Hack The Box】windows练习-- Bankrobber
    grpc的粗浅理解与示例
    【数据库——MySQL(实战项目1)】(4)图书借阅系统——触发器
    Springboot vue elementui 医院管理系统案例源码
    你所不知道的端口耗尽(一)
    Linux常用命令:htop(交互式进程查看器)【后台运行及查看状态命令】【top命令的升级版】
    C# wpf使用ffmpeg命令行实现录屏
    新兴市场潜力无限,ADVANCE.AI风控产品助中国出海企业筑牢安全发展基础
    看骰子的六个面需要多少次
    详解诊断数据库ODX-F
  • 原文地址:https://blog.csdn.net/weixin_50437588/article/details/126218168