[程序员代码面试指南]数组和矩阵问题-找到无序数组中最小的k个数(堆排序)
题目链接
题目描述
从无序序列,找到最小topk个元素。
解题思路
使用大根堆维护最小topk个元素:
- 首先前k个元素建立大根堆(从最后一个非叶节点(数组长度/2-1,结点从0计:大致是最后一个节点j与最后一个非叶节点i满足j=2i+1或j=2i+2,PS数组长度len=j+1,大概是有一些取整的原因设计,总之验证这是对的)至根节点(数组第一个元素)调整)。
- 之后维护这个最小k个元素的大根堆(比较后面的元素与根顶元素,若新元素小则替换掉堆顶元素,并进入调整)。
- 最终堆中元素即为所求。
查找topk时间复杂度:O(nlogk)。
相关知识:堆排序
堆的定义
堆是具有以下性质的完全二叉树:
每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。
用数组表示一个堆结构,堆的定义就是:(结点从0计)
大根堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]
小根堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]
堆排序步骤
第一步:建堆:从最后一个非叶节点(数组长度/2-1,结点从0计。推导:最后一个节点下标j与最后一个非叶节点i的关系满足j=2i+1或j=2i+2=>i=j/2-1或j/2-0.5,)至根节点(数组第一个元素)调整。
第二步:反复执行交换、调整:将堆顶元素与树最后一个叶节点交换,从上至下调整剩余节点为堆(称为筛选);再将堆顶元素与最后一个叶节点交换...直到所有元素组成序列。大根堆对应升序,小根堆对应降序。
堆排序特点
- 时间复杂度:平均、最好、最坏均为O(nlogn)
- 相比快排,堆排序的最坏时间复杂度更优,这是堆排序最大的优点。所以堆排序适合记录数n较大的文件,不适合记录数较小的文件。
- 对深度为K的堆,筛选算法关键字比较次数至多为2(K-1);则在建n个元素,深度为h的堆时,总共进行的关键字比较次数不超过4n(公式见数据结构严蔚敏P282底栏??);又,n个结点的完全二叉树深度为log2n」+1,所以最坏时间复杂度O(nlogn).
堆排序参考链接
https://www.cnblogs.com/chengxiao/p/6129630.html
代码
import java.util.*;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> maxRootHeap = new ArrayList<Integer>();
if(k<1||k>input.length){
return maxRootHeap;
}
for(int i=0;i<k;++i) {
maxRootHeap.add(input[i]);
}
//建堆
buildMaxRootHeap(maxRootHeap);
//调整
for(int i=k;i<input.length;++i) {
if(input[i]<maxRootHeap.get(0)) {
maxRootHeap.set(0, input[i]);
heapify(maxRootHeap,0,k-1);
}
}
return maxRootHeap;
}
private void buildMaxRootHeap(ArrayList<Integer> maxRootHeap) {
for(int i=maxRootHeap.size()/2-1;i>=0;--i) {
heapify(maxRootHeap,i,maxRootHeap.size()-1);
}
}
//调整以index索引为根节点的堆
private void heapify(ArrayList<Integer> maxRootHeap,int index,int heapSize) {//heapSize 指堆最后一个节点的索引
int lIdx=2*index+1;
int rIdx=2*index+2;
int maxIdx=index;
while(lIdx<=heapSize) {
if(maxRootHeap.get(lIdx)>maxRootHeap.get(index)) {
maxIdx=lIdx;
}
if(rIdx<=heapSize&&maxRootHeap.get(rIdx)>maxRootHeap.get(maxIdx)) {
maxIdx=rIdx;
}
if(maxIdx!=index) {
swap(maxRootHeap,index,maxIdx);
}
else {
break;
}
index=maxIdx;
lIdx=2*index+1;
rIdx=2*index+2;
}
}
private void swap(ArrayList<Integer> heap,int idx1,int idx2) {
int temp=heap.get(idx1);
heap.set(idx1,heap.get(idx2));
heap.set(idx2, temp);
}
}
[程序员代码面试指南]数组和矩阵问题-找到无序数组中最小的k个数(堆排序)的更多相关文章
- 《程序员代码面试指南》第八章 数组和矩阵问题 找到无序数组中最小的k 个数
题目 找到无序数组中最小的k 个数 java代码 package com.lizhouwei.chapter8; /** * @Description: 找到无序数组中最小的k 个数 * @Autho ...
- 程序员代码面试指南:IT名企算法与数据结构题目最优解
第1章栈和队列 1设计一个有getMin功能的栈(士★☆☆☆) 1由两个栈组成的队列(尉★★☆☆) 5如何仅用递归函数和栈操作逆序一个栈(尉★★☆☆) 8猫狗队列(士★☆☆☆)10用一个栈实现另一 ...
- 【算法】数组与矩阵问题——找到无序数组中最小的k个数
/** * 找到无序数组中最小的k个数 时间复杂度O(Nlogk) * 过程: * 1.一直维护一个有k个数的大根堆,这个堆代表目前选出来的k个最小的数 * 在堆里的k个元素中堆顶的元素是最小的k个数 ...
- 程序员代码面试指南 IT名企算法与数据结构题目最优解
原文链接 这是一本程序员面试宝典!书中对IT名企代码面试各类题目的最优解进行了总结,并提供了相关代码实现.针对当前程序员面试缺乏权威题目汇总这一痛点,本书选取将近200道真实出现过的经典代码面试题,帮 ...
- 《程序员代码面试指南》第八章 数组和矩阵问题 打印N 个数组整体最大的Top K
题目 打印N 个数组整体最大的Top K java代码 package com.lizhouwei.chapter8; /** * @Description: 打印N 个数组整体最大的Top K * ...
- [程序员代码面试指南]递归和动态规划-最长公共子串问题(DP,LCST)
问题描述 如题. 例:输入两个字符串 str1="1AB234",str2="1234EF" ,应输出最长公共子串"234". 解题思路 状 ...
- [程序员代码面试指南]栈和队列-最大值减去最小值 小于或等于num 的子数组的数量(单调队列)
题目 给定数组arr和整数num,求数组的子数组中有多少个的满足"最大值减去最小值<=num". 解题思路 分析题目,有结论: 如果数组arr[i...j]满足条件,则它的每 ...
- 《程序员代码面试指南》第一章 栈和队列 设计一个有getMin功能的栈
题目 实现一个特殊的栈,在实现栈的基本功能上,再实现返回栈中最小的元素的操作 要求 1. pop.push.getMin操作时间复杂度都是O(1) 2. 设计的栈类型可以使用现成的栈结构 java代码 ...
- 《程序员代码面试指南》第五章 字符串问题 去掉字符串中连续出现k 个0 的子串
题目 去掉字符串中连续出现k 个0 的子串 java代码 package com.lizhouwei.chapter5; /** * @Description: 去掉字符串中连续出现k 个0 的子串 ...
随机推荐
- sklearn错误
1.No module named 'sklearn.cross_validation' sklearn.cross_validation会报错,关键在于新版本的sklearn没有cross_vali ...
- 国家码和reginCode映射关系
import org.apache.commons.lang.StringUtils; import java.util.HashMap; import java.util.Map; public c ...
- windows使用im4java 提示FileNotFoundException
1)安装imageMagic时候要勾上convert那一行,确保安装目录下有convert.exe 2)使用image4java的全局类里面加上 //ImageMagick的安装路径 public s ...
- wine install
# yum -y groupinstall 'Development Tools' # yum -y install libX11-devel libxml2-devel libxslt-devel ...
- Java Web组件Servlet、Filter、Listener
一.Servlet 类javax.servlet.http.HttpServlet; 1.是单例模式,一个web容器中只有一个实例.服务器调用它的service方法进行请求处理, service方法又 ...
- 关闭Cadence Orcad Capture CIS原理图弹出startpage页面的方法
打开原理图工具 Orcad Capture CIS 时,总是会弹出startpage 页面,有时候感觉这个东西挺碍事的,还是关了感觉好.解决方法如下:(1) View---Toolbar----Com ...
- Cesium学习网址
不错的案例介绍: 根据地形瓦片直接绘制高程.坡度及等高线 同一场景下显示两个不同的瓦片图层 https://cloud.tencent.com/developer/article/1113355 绘制 ...
- omniPlan密匙
密钥所有者都是youliyuan.OmniPlan 3:HOMJ-QOJH-OIBN-TNIH-HWUN-TEEH-WUNNKWO-HVKB-JAZE-UIHH-XAVY-BEEX-AVYBCRW-M ...
- CUDA编程模型——组织并行线程2 (1D grid 1D block)
在”组织并行编程1“中,通过组织并行线程为”2D grid 2D block“对矩阵求和,在本文中通过组织为 1D grid 1D block进行矩阵求和.一维网格和一维线程块的结构如下图: 其中,n ...
- Docker笔记——Docker安装及制作镜像
1 Docker安装本文中Docker运行环境为Ubuntu 14.04.1 LTS 3.13.0-32-generic x64参考:https://docs.docker.com/v1.11/eng ...