本文参考自《剑指offer》一书,代码采用Java语言。

更多:《剑指Offer》Java实现合集  

题目 

  输入n个整数,找出其中最小的k个数。例如输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

思路

  思路一:剑指offer(39) 数组中出现次数超过一半的数字中使用partition()方法,基于数组的第k个数字调整,使得更小的k个数字都在数组左边即可。

  思路二:依次遍历n个整数,用一个容器存放最小的k个数字,每遇到比容器中最大的数字还小的数字时,将最大值替换为该数字。容器可以使用最大堆或者红黑树来实现。本文根据堆排序的原理来实现。

测试算例 

  1.功能测试(数组中存在/不存在重复数字)

  2.边界值测试(k=1或者等于数组长度)

  2.特殊测试(null、k<1、k大于数组长度)

Java代码

//题目:输入n个整数,找出其中最小的k个数。例如输入4、5、1、6、2、7、3、8
//这8个数字,则最小的4个数字是1、2、3、4。 public class KLeastNumbers { /*
* 方法一:采用partition()
*/
public ArrayList<Integer> GetLeastNumbers_Solution1(int [] input, int k) {
ArrayList<Integer> leastNumbers = new ArrayList<Integer>();
while(input==null || k<=0 || k>input.length)
return leastNumbers;
int start=0;
int end=input.length-1;
int index=partition(input,start,end);
while(index!=k-1){
if(index<k-1){
start=index+1;
index=partition(input,start,end);
}else{
end=index-1;
index=partition(input,start,end);
}
}
for(int i=0;i<k;i++){
leastNumbers.add(input[i]);
}
return leastNumbers;
} private int partition(int[] arr, int start,int end){
int pivotKey=arr[start];
while(start<end){
while(start<end && arr[end]>=pivotKey)
end--;
swap(arr,start,end);
while(start<end && arr[start]<=pivotKey)
start++;
swap(arr,start,end);
}
return start;
} private void swap(int[] arr, int i,int j){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
} /*
* 方法二:基于堆的容器
*/
public ArrayList<Integer> GetLeastNumbers_Solution2(int [] input, int k) {
ArrayList<Integer> leastNumbers = new ArrayList<Integer>();
while(input==null || k<=0 || k>input.length)
return leastNumbers;
int[] numbers=new int[k]; //用于放最小的k个数
for(int i=0;i<k;i++)
numbers[i]=input[i];//先放入前k个数
for(int i=k/2-1;i>=0;i--){
adjustHeap(numbers,i,k-1);//将数组构造成最大堆形式
}
for(int i=k;i<input.length;i++){
if(input[i]<numbers[0]){ //存在更小的数字时
numbers[0]=input[i];
adjustHeap(numbers,0,k-1);//重新调整最大堆
}
}
for(int n:numbers)
leastNumbers.add(n);
return leastNumbers;
} //最大堆的调整方法,忘记时可以复习一下堆排序。
private void adjustHeap(int[] arr,int start,int end){
int temp=arr[start];
int child=start*2+1;
while(child<=end){
if(child+1<=end && arr[child+1]>arr[child])
child++;
if(arr[child]<temp)
break;
arr[start]=arr[child];
start=child;
child=child*2+1;
}
arr[start]=temp;
}
}

大顶堆可以用PriorityQueue实现,所以方法二可利用API实现如下:

    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> list = new ArrayList<>();
if(input==null || input.length<k || k<=0)
return list;
PriorityQueue<Integer> heap = new PriorityQueue<>(k,(i1, i2)->(i2-i1));
for(int i=0; i<input.length; i++){
if(heap.size()<k){
heap.offer(input[i]);
}else if(heap.peek()>input[i]){
heap.poll();
heap.offer(input[i]);
}
}
for(int i: heap)
list.add(i);
return list;
}

  

收获

  1.k小于等于0的情况别忘记了

  2.方法二,只需要在原始数组中进行读入操作,而所有的写操作和判断都是在容器中进行的,不用反复读取原始数组,思想非常好。

  3.记得要弄清楚是否可以改变原始输入的数组。

  4.partition函数:即是快速排序的基础,也可以用来查找n个数中第k大的数字。

  5.当涉及到频繁查找和替换最大最小值时,二叉树是非常合适的数据结构,要能想到堆和二叉树。

  6. PriorityQueue重点:

    * 大顶堆与小顶堆的构建: new Comporator()

    * 如何插值: heap.offer(e)

    * 如何获取堆顶的值: heap.peek(), heap.poll()

更多:《剑指Offer》Java实现合集  

  

【Java】 剑指offer(40) 最小的k个数的更多相关文章

  1. 剑指 Offer 40. 最小的k个数 + 优先队列 + 堆 + 快速排序

    剑指 Offer 40. 最小的k个数 Offer_40 题目描述 解法一:排序后取前k个数 /** * 题目描述:输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7. ...

  2. 剑指 Offer 40. 最小的k个数

    剑指 Offer 40. 最小的k个数 输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 示例 1: 输入:ar ...

  3. 每日一题 - 剑指 Offer 40. 最小的k个数

    题目信息 时间: 2019-06-30 题目链接:Leetcode tag: 快排 难易程度:中等 题目描述: 输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3. ...

  4. 【剑指Offer】最小的K个数 解题报告(Python)

    [剑指Offer]最小的K个数 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interviews 题目 ...

  5. Go语言实现:【剑指offer】最小的K个数

    该题目来源于牛客网<剑指offer>专题. 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. Go语言实现: fu ...

  6. 《剑指offer》最小的k个数

    本题来自<剑指offer> 反转链表 题目: 思路: C++ Code: Python Code: 总结:

  7. 剑指OFFER之最小的K个数(九度OJ1371)

    题目描述: 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 输入: 每个测试案例包括2行: 第一行为2个整数n,k(1< ...

  8. 剑指Offer 29. 最小的K个数 (其他)

    题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4. 题目地址 https://www.nowcoder.com/prac ...

  9. 【剑指offer】最小的K个数

    一.题目: 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 二.思路: 一群大牛在讨论用噼里啪啦各种排序,复杂度一般也都是O ...

随机推荐

  1. Linux - DDOS检测

    netstat  netstat -na #显示所有连接到服务器的活跃的网络连接 netstat -an | grep : | sort # 只显示连接到80段口的活跃的网络连接,80是http端口, ...

  2. 第16月第15天 glut

    1. https://tokoik.github.io/opengl/libglut.html https://github.com/wistaria/wxtest/tree/master/C htt ...

  3. [转]GDB-----1.GDB概述

    作者: liigo原文链接: http://blog.csdn.net/liigo/archive/2006/01/17/582231.aspx 1.前言 本文写给主要工作在Windows操作系统下而 ...

  4. c# LINQ 使用

    linq是个好东西,让开发人员省时省力.很多人可能只知道怎么使用, 对它没有全面深入的了解.所谓磨刀不误砍柴工,今天就来学习下. 一.与LINQ有关的语言特性 1.扩展方法 在System.Linq命 ...

  5. Windows10 + Visual Studio 2017 + CMake +OpenCV编译、开发环境配置及测试

    由于最近需要使用OpenCV,本人需要在自己的PC上使用OpenCV,因此最近一直在研究如何使用Visual Studio编译OpenCV源代码并搭建开发环境,折腾了很长时间,查阅了很多相关资料,终于 ...

  6. plsql developer日期类型数据格式不对如何设置?

    当把一个数据库中的数据复制到另一个数据库时,如果数据中包含日期类型,会提示数据格式不正确.或者两个plsql developer设置不同,但实际上建表语句一样. 此时可在plsql中做如下设置: 首选 ...

  7. jumpserver会话终端故障

    查看jumpserver的终端,发现无法访问,情况如下图 页面中提到,需要部署luna,coco和nginx的url分发. 然后进入到jumpserver的服务器,发现nginx启动了,但是没有coc ...

  8. LinkedList源码分析笔记(jdk1.8)

    1.特点 LinkedList的底层实现是由一个双向链表实现的,可以从两端作为头节点遍历链表. 允许元素为null 线程不安全 增删相对ArrayList快,改查相对ArrayList慢(curd都会 ...

  9. Android中PopupWindow用法

    参考资料链接:http://developer.android.com/reference/android/widget/PopupWindow.html 在Android中有很多级别的Window, ...

  10. MySQL双版本共存解决方案

    案例是MySQL5.5(3306端口)和MySQL5.6(3307端口). 1. 修改C:\Program Files (x86)\MySQL\MySQL Server 5.6\下的my-xxx.in ...