博客
关于我
TopK问题-优先队列和基于partition减治、自己实现堆调整3种方法
阅读量:481 次
发布时间:2019-03-07

本文共 2373 字,大约阅读时间需要 7 分钟。

在这里插入图片描述
1. 思路1:求第k大,维护一个小根堆,用优先队列priority_queue

  • 过程:向小根堆中插入k个数,遍历剩下的n-k个数,当前数比堆顶大时,交换他们的值。
  • 这样遍历完,堆顶是小根堆k个数中最小的,且比剩余的n-k的数都大,因此堆顶即为所求;此外,小根堆中所有的数是整个数组的前k大,堆顶就是第k大

代码如下(Leetcode 215):

class Solution {   public:    int findKthLargest(vector
& nums, int k) { priority_queue
,greater
> q; int i=0; for(;i
q.top()){ q.pop(); q.push(nums[i]); } return q.top(); }};

运行结果:

在这里插入图片描述

2. 思路2:基于快排思想(partition)

  • partition过程(升序):
  1. 找当前arr最左边作为基准ref
  2. 循环条件:left < right
  • 右➡️左:找到比ref小的,放在左边
  • 左➡️右:找到比ref大的,放在右边
  1. 当left == right时结束循环,这个坐标就是ref应该在的index
int partition(vector
& arr,int l,int r){ int ref = arr[l]; while(l
=ref) r--; arr[l]=arr[r]; while(l

回到此题:

  • 首先,不是快速排序,而是基于快速排序中的partition思想。快速排序对index左右都进行排序,每个子问题都要解决,本题目只解决一个子问题即可。
  • 找第K大的,因此是降序,相应的改一下partition中的判断条件即可,过程如下:
  1. 对最左数作为基准ref进行partition,得到该ref应在的index
  2. left < right 时进行循环:
  • 若index < K-1 : 说明第 K 大在右边,left = index + 1,继续partition
  • 若index > K-1:说明第 K 大在左边,right = index -1,继续partition
  1. left == right 时第K个数即为第K大

代码如下(牛客NC88):

class Finder {   public:    int findKth(vector
a, int n, int K) { int left=0,right=n-1; while(left
& a,int left,int right){ int ref=a[left]; while(left < right){ while(left
=ref) left++; a[right]=a[left]; } a[left]=ref; return left; }};

在这里插入图片描述

3. 思路3:自己实现堆调整

  1. 插入前k个元素时,priority_queue每次push都要进行一次堆调整,共需要k次;
  • 如果自己实现,可以将前k个元素仅经过1次堆调整建成初始小根堆
  1. 对于后面的n-k个元素,每次遇到比堆顶大的,priority_queue都要push、pop经过2次堆调整;
  • 如果自己实现,可以交换这两个元素,然后进行1次堆调整
  1. 因此自己实现堆调整理论上来说时间可以更短,用数组模拟堆调整的方法在之前的博客已经提到过了

代码如下:

class Solution {   public:    int findKthLargest(vector
& nums, int k) { //首先进行堆调整,把前k个建为小根堆 for(int i=k/2-1;i>=0;i--) heapAdjust(nums,i,k-1); //对后面的n-k个数,如果比堆顶大就交换,然后再进行堆调整 for(int j=k;j
nums[0]){ swap(nums[0],nums[j]); heapAdjust(nums,0,k-1); } } return nums[0]; } //小根堆的调整 void heapAdjust(vector
& nums,int start,int end){ int dad=start; int son=2*dad+1; while(son<=end){ if(son+1<=end && nums[son+1]
  • 12ms为自己实现堆调整,20ms为使用priority_queue
    在这里插入图片描述

转载地址:http://abzcz.baihongyu.com/

你可能感兴趣的文章
MySQL5.1安装
查看>>
mysql5.5和5.6版本间的坑
查看>>
mysql5.5最简安装教程
查看>>
mysql5.6 TIME,DATETIME,TIMESTAMP
查看>>
mysql5.6.21重置数据库的root密码
查看>>
Mysql5.6主从复制-基于binlog
查看>>
MySQL5.6忘记root密码(win平台)
查看>>
MySQL5.6的Linux安装shell脚本之二进制安装(一)
查看>>
MySQL5.6的zip包安装教程
查看>>
mysql5.7 for windows_MySQL 5.7 for Windows 解压缩版配置安装
查看>>
Webpack 基本环境搭建
查看>>
mysql5.7 安装版 表不能输入汉字解决方案
查看>>
MySQL5.7.18主从复制搭建(一主一从)
查看>>
MySQL5.7.19-win64安装启动
查看>>
mysql5.7.19安装图解_mysql5.7.19 winx64解压缩版安装配置教程
查看>>
MySQL5.7.37windows解压版的安装使用
查看>>
mysql5.7免费下载地址
查看>>
mysql5.7命令总结
查看>>
mysql5.7安装
查看>>
mysql5.7性能调优my.ini
查看>>