博客
关于我
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/

你可能感兴趣的文章
MySQL原理、设计与应用全面解析
查看>>
MySQL原理简介—1.SQL的执行流程
查看>>
MySQL参数调优详解
查看>>
mysql参考触发条件_MySQL 5.0-触发器(参考)_mysql
查看>>
MySQL及navicat for mysql中文乱码
查看>>
MySqL双机热备份(二)--MysqL主-主复制实现
查看>>
MySql各种查询
查看>>
mysql同主机下 复制一个数据库所有文件到另一个数据库
查看>>
mysql启动以后会自动关闭_驾照虽然是C1,一直是开自动挡的车,会不会以后就不会开手动了?...
查看>>
mysql启动和关闭外键约束的方法(FOREIGN_KEY_CHECKS)
查看>>
Mysql启动失败解决过程
查看>>
MySQL启动失败:Can't start server: Bind on TCP/IP port
查看>>
mysql启动报错
查看>>
mysql启动报错The server quit without updating PID file几种解决办法
查看>>
MySQL命令行登陆,远程登陆MySQL
查看>>
mysql命令:set sql_log_bin=on/off
查看>>
mySQL和Hive的区别
查看>>
MySQL和Java数据类型对应
查看>>
mysql和oorcale日期区间查询【含左右区间问题】
查看>>
MySQL和SQL入门
查看>>