博客
关于我
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学习总结(62)——MySQL连接com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link问题
查看>>
Mysql学习总结(63)——Mysql数据库架构方案选择与分析
查看>>
Mysql学习总结(64)——Mysql配置文件my.cnf各项参数解读
查看>>
Mysql学习总结(65)——项目实战中常用SQL实践总结
查看>>
Mysql学习总结(66)——设置MYSQL数据库编码为UTF-8
查看>>
Mysql学习总结(67)——MYSQL慢查询日志
查看>>
Mysql学习总结(68)——MYSQL统计每天、每周、每月、每年数据 SQL 总结
查看>>
Mysql学习总结(69)——Mysql EXPLAIN 命令使用总结
查看>>
Mysql学习总结(6)——MySql之ALTER命令用法详细解读
查看>>
Mysql学习总结(70)——MySQL 优化实施方案
查看>>
Mysql学习总结(71)——MySQL 重复记录查询与删除总结
查看>>
Mysql学习总结(71)——数据库介绍(MySQL安装 体系结构、基本管理)再回顾
查看>>
Mysql学习总结(73)——MySQL 查询A表存在B表不存在的数据SQL总结
查看>>
Mysql学习总结(76)——MySQL执行计划(explain)结果含义总结
查看>>
Mysql学习总结(77)——温故Mysql数据库开发核心原则与规范
查看>>
Mysql学习总结(78)——MySQL各版本差异整理
查看>>
Mysql学习总结(79)——MySQL常用函数总结
查看>>
Mysql学习总结(7)——MySql索引原理与使用大全
查看>>
Mysql学习总结(80)——统计数据库的总记录数和库中各个表的数据量
查看>>
Mysql学习总结(81)——为什么MySQL不推荐使用uuid或者雪花id作为主键?
查看>>