博客
关于我
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.7安装
查看>>
mysql5.7性能调优my.ini
查看>>
MySQL5.7新增Performance Schema表
查看>>
Mysql5.7深入学习 1.MySQL 5.7 中的新增功能
查看>>
Webpack 之 basic chunk graph
查看>>
Mysql5.7版本单机版my.cnf配置文件
查看>>
mysql5.7的安装和Navicat的安装
查看>>
mysql5.7示例数据库_Linux MySQL5.7多实例数据库配置
查看>>
Mysql8 数据库安装及主从配置 | Spring Cloud 2
查看>>
mysql8 配置文件配置group 问题 sql语句group不能使用报错解决 mysql8.X版本的my.cnf配置文件 my.cnf文件 能够使用的my.cnf配置文件
查看>>
MySQL8.0.29启动报错Different lower_case_table_names settings for server (‘0‘) and data dictionary (‘1‘)
查看>>
MYSQL8.0以上忘记root密码
查看>>
Mysql8.0以上重置初始密码的方法
查看>>
mysql8.0新特性-自增变量的持久化
查看>>
Mysql8.0注意url变更写法
查看>>
Mysql8.0的特性
查看>>
MySQL8修改密码报错ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
查看>>
MySQL8修改密码的方法
查看>>
Mysql8在Centos上安装后忘记root密码如何重新设置
查看>>
Mysql8在Windows上离线安装时忘记root密码
查看>>