求数组中最小的k个数
题目:输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
package test; import java.util.ArrayList;
import java.util.Comparator;
import java.util.PriorityQueue; import org.junit.Test; public class GetLeastNumbers_Solution {
/**
* 基于优先队列,时间复杂度为o(nlogk)
*
* @param input
* @param k
* @return
*/
public ArrayList<Integer> GetLeastNumbers_SolutionPriorityQuene(
int[] input, int k) {
ArrayList<Integer> result = new ArrayList<Integer>();
if (input == null || input.length == 0 || k <= 0 || k > input.length)
return result;
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(
new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
for (int i = 0; i < k; i++) {
maxHeap.offer(input[i]);
}
for (int j = k; j < input.length; j++) {
if (input[j] < maxHeap.peek()) {
maxHeap.poll();
maxHeap.offer(input[j]);
}
}
for (Integer integer : maxHeap) {
result.add(integer);
} return result;
} /**
* 基于堆排序,时间复杂度为o(nlogk)
*
* @param input
* @param k
* @return
*/
public ArrayList<Integer> GetLeastNumbers_SolutionMaxHeap(int[] input, int k) {
ArrayList<Integer> result = new ArrayList<Integer>();
if (input == null || input.length == 0 || k <= 0 || k > input.length)
return result;
//构建最大堆
builtMaxHeap(input,k-1);
for (int i = k; i < input.length; i++) {
//数组k位后的数字比堆顶小
if (input[k] < input[0]) {
input[0] = input[k];
//调整堆
builtMaxHeap(input, k - 1);
}
}
for (int i = 0; i < k; i++) {
result.add(input[i]);
}
return result;
} /**
* 构建、调整最大堆
* @param a
* @param lastIndex
*/
public void builtMaxHeap(int[]a,int lastIndex){
int parentIndex = ((lastIndex-1) >> 1);
//从最后一个节点的父节点开始
for(int i=parentIndex;i>=0;i--){
//存在子节点
while (i*2+1<=lastIndex){
int leftIndex = i*2+1;
int rightIndex = i*2+2;
int biggerIndex = leftIndex;
//存在右结点
if (rightIndex <= lastIndex){
if(a[rightIndex] > a[biggerIndex]){
biggerIndex = rightIndex;
}
}
//子节点中最大节点大于父节点
if (a[biggerIndex] > a[i]){
swap(a,i,biggerIndex);
i = biggerIndex;
}else{
break;
}
}
}
} /**
* 基于Partition函数,时间复杂度为o(n),原数组已被修改
*
* @param input
* @param k
* @return
*/
public ArrayList<Integer> GetLeastNumbers_SolutionPartition(int[] input,
int k) {
ArrayList<Integer> result = new ArrayList<Integer>();
if (input == null || input.length == 0 || k <= 0 || k > input.length)
return result; int left = 0;
int right = input.length - 1;
int index = partition(input, 0, right); while (index != k - 1) {
if (index > k - 1) {
right = index - 1;
index = partition(input, left, right);
} else {
left = index + 1;
index = partition(input, left, right);
}
}
for (int i = 0; i < k; i++) {
result.add(input[i]);
} return result;
} /**
* partition函数
* @param a
* @param left
* @param right
* @return
*/
public int partition(int[] a, int left, int right) {
while (left < right) {
while (left < right && a[left] <= a[right]) {
right--;
}
if (left < right) {
swap(a, left, right);
}
while (left < right && a[left] <= a[right]) {
left++;
}
if (left < right) {
swap(a, left, right);
} }
return left;
} public void swap(int[] a, int i, int j) {
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
} @Test
public void testGetLeastNumbers_Solution() {
int[] a = { 4, 5, 1, 6, 2, 7, 3, 8 };
int k = 4;
ArrayList<Integer> list = GetLeastNumbers_SolutionPartition(a, k);
System.out.println(list.toString()); ArrayList<Integer> list2 = GetLeastNumbers_SolutionPriorityQuene(a, k);
System.out.println(list2.toString()); ArrayList<Integer> list3 = GetLeastNumbers_SolutionMaxHeap(a, k);
System.out.println(list3.toString()); }
}
除了基于优先队列,时间复杂度为O(nlogk)、堆排序,时间复杂度为O(nlogk)、partition函数,时间复杂度为O(n)的解法之外,还有基于冒泡排序的解法时间复杂度为(nk)。
求数组中最小的k个数的更多相关文章
- 求一个数组中最小的K个数
方法1:先对数组进行排序,然后遍历前K个数,此时时间复杂度为O(nlgn); 方法2:维护一个容量为K的最大堆(<算法导论>第6章),然后从第K+1个元素开始遍历,和堆中的最大元素比较,如 ...
- 【算法】数组与矩阵问题——找到无序数组中最小的k个数
/** * 找到无序数组中最小的k个数 时间复杂度O(Nlogk) * 过程: * 1.一直维护一个有k个数的大根堆,这个堆代表目前选出来的k个最小的数 * 在堆里的k个元素中堆顶的元素是最小的k个数 ...
- [算法]找到无序数组中最小的K个数
题目: 给定一个无序的整型数组arr,找到其中最小的k个数. 方法一: 将数组排序,排序后的数组的前k个数就是最小的k个数. 时间复杂度:O(nlogn) 方法二: 时间复杂度:O(nlogk) 维护 ...
- 《程序员代码面试指南》第八章 数组和矩阵问题 找到无序数组中最小的k 个数
题目 找到无序数组中最小的k 个数 java代码 package com.lizhouwei.chapter8; /** * @Description: 找到无序数组中最小的k 个数 * @Autho ...
- 小米笔试题:无序数组中最小的k个数
题目描述 链接:https://www.nowcoder.com/questionTerminal/ec2575fb877d41c9a33d9bab2694ba47?source=relative 来 ...
- 窥探算法之美妙——寻找数组中最小的K个数&python中巧用最大堆
原文发表在我的博客主页,转载请注明出处 前言 不论是小算法或者大系统,堆一直是某种场景下程序员比较亲睐的数据结构,而在python中,由于数据结构的极其灵活性,list,tuple, dict在很多情 ...
- [剑指offer]数组中最小的K个数,C++实现
原创博文,转载请注明出处! http://github.com/wanglei5205 http://cnblogs.com/wanglei5205 # 题目 输入n个整数,找出其中最小的K个数.例如 ...
- 找到数组中最小的k个数
/*输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字, 则最小的4个数字是1.2.3.4. 示例 1: 输入:arr = [3,2,1], k = ...
- 面试题四十:数组中最小的k个数
方法一:先排序后寻找前k个数: 方法二:受面试题三十九,寻找超过一半的数的启发,只把里面的middle改成k-1就行: void HalfNum( int [ ] Array ,int k){ int ...
随机推荐
- 3.2 while 循环
Python 编程中 while 语句用于循环执行程序,即在条件满足的情况下,循环执行某段代码.所以就需要在循环的代码块中设计一种使代码块循环执行一定次数后是while语句的条件不满足,从而中止whi ...
- c#IO的学习
常见应用方面 一.路径的相关操作,如判定路径是否合法,路径类型,路径的特定部分,合并路径,系统文件夹路径等内容:二.相关通用文件对话框,这些对话框可以帮助我们操作文件系统中的文件和目录:三.文件.目录 ...
- PAT甲级 1004 树
思路:直接遍历整棵树判定每个结点是否有孩子,没有则把当前高度的叶子节点数加一. AC代码 #include <stdio.h> #include <string.h> #inc ...
- PAT乙级1065 map
思路:检查某个客人是否有伴侣,如果有,伴侣是否也出现即可. 注意:0个单身狗的时候,不要输出多余的'\n', 否则会出现格式错误. AC代码 #include <stdio.h> #inc ...
- 网卡驱动引起openstack的mtu问题
一套Pike版本的openstack测试环境,使用vlan模式的网络,数据网网卡使用的是绿联的usb百兆网卡,遇到了虚拟机网络异常的问题.同一个vlan下,不同宿主机上的两台虚拟机,相互之间可以pin ...
- 【java学习笔记】正则表达式
一.正则表达式 1.预定义字符集 . 表示任意一个字符 \d 表示任意一个数字 \w 表示任意一个单词字符(只能是数字.字母.下划线) \s 表示任意一个空白字符(\t\r\n\f\x0B) \D ...
- 5.1 TLP的格式
当处理器或者其他PCIe设备访问PCIe设备时,所传送的数据报文首先通过事务层被封装为一个或者多个TLP,之后才能通过PCIe总线的各个层次发送出去.TLP的基本格式如图5?1所示. 一个完整的TLP ...
- 实战DeviceIoControl 之三:制作磁盘镜像文件
Q DOS命令DISKCOPY给我很深的印象,现在也有许多"克隆"软件,可以对磁盘进行全盘复制.我想,要制作磁盘镜像文件,DeviceIoControl应该很有用武之地吧? A 是 ...
- FusionCharts封装-Value
Data.java: /** * @Title:Data.java * @Package:com.fusionchart.model * @Description:FusionCharts 封装dat ...
- 安装coreseek cannot find input file: src/Makefile.in 错误解决方法
安装coreseek 出现了cannot find input file: src/Makefile.in 解决方法如下 >autoheader >automake --add-missi ...