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

  1. package test;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.Comparator;
  5. import java.util.PriorityQueue;
  6.  
  7. import org.junit.Test;
  8.  
  9. public class GetLeastNumbers_Solution {
  10. /**
  11. * 基于优先队列,时间复杂度为o(nlogk)
  12. *
  13. * @param input
  14. * @param k
  15. * @return
  16. */
  17. public ArrayList<Integer> GetLeastNumbers_SolutionPriorityQuene(
  18. int[] input, int k) {
  19. ArrayList<Integer> result = new ArrayList<Integer>();
  20. if (input == null || input.length == 0 || k <= 0 || k > input.length)
  21. return result;
  22. PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(
  23. new Comparator<Integer>() {
  24. @Override
  25. public int compare(Integer o1, Integer o2) {
  26. return o2.compareTo(o1);
  27. }
  28. });
  29. for (int i = 0; i < k; i++) {
  30. maxHeap.offer(input[i]);
  31. }
  32. for (int j = k; j < input.length; j++) {
  33. if (input[j] < maxHeap.peek()) {
  34. maxHeap.poll();
  35. maxHeap.offer(input[j]);
  36. }
  37. }
  38. for (Integer integer : maxHeap) {
  39. result.add(integer);
  40. }
  41.  
  42. return result;
  43. }
  44.  
  45. /**
  46. * 基于堆排序,时间复杂度为o(nlogk)
  47. *
  48. * @param input
  49. * @param k
  50. * @return
  51. */
  52. public ArrayList<Integer> GetLeastNumbers_SolutionMaxHeap(int[] input, int k) {
  53. ArrayList<Integer> result = new ArrayList<Integer>();
  54. if (input == null || input.length == 0 || k <= 0 || k > input.length)
  55. return result;
  56. //构建最大堆
  57. builtMaxHeap(input,k-1);
  58. for (int i = k; i < input.length; i++) {
  59. //数组k位后的数字比堆顶小
  60. if (input[k] < input[0]) {
  61. input[0] = input[k];
  62. //调整堆
  63. builtMaxHeap(input, k - 1);
  64. }
  65. }
  66. for (int i = 0; i < k; i++) {
  67. result.add(input[i]);
  68. }
  69. return result;
  70. }
  71.  
  72. /**
  73. * 构建、调整最大堆
  74. * @param a
  75. * @param lastIndex
  76. */
  77. public void builtMaxHeap(int[]a,int lastIndex){
  78. int parentIndex = ((lastIndex-1) >> 1);
  79. //从最后一个节点的父节点开始
  80. for(int i=parentIndex;i>=0;i--){
  81. //存在子节点
  82. while (i*2+1<=lastIndex){
  83. int leftIndex = i*2+1;
  84. int rightIndex = i*2+2;
  85. int biggerIndex = leftIndex;
  86. //存在右结点
  87. if (rightIndex <= lastIndex){
  88. if(a[rightIndex] > a[biggerIndex]){
  89. biggerIndex = rightIndex;
  90. }
  91. }
  92. //子节点中最大节点大于父节点
  93. if (a[biggerIndex] > a[i]){
  94. swap(a,i,biggerIndex);
  95. i = biggerIndex;
  96. }else{
  97. break;
  98. }
  99. }
  100. }
  101. }
  102.  
  103. /**
  104. * 基于Partition函数,时间复杂度为o(n),原数组已被修改
  105. *
  106. * @param input
  107. * @param k
  108. * @return
  109. */
  110. public ArrayList<Integer> GetLeastNumbers_SolutionPartition(int[] input,
  111. int k) {
  112. ArrayList<Integer> result = new ArrayList<Integer>();
  113. if (input == null || input.length == 0 || k <= 0 || k > input.length)
  114. return result;
  115.  
  116. int left = 0;
  117. int right = input.length - 1;
  118. int index = partition(input, 0, right);
  119.  
  120. while (index != k - 1) {
  121. if (index > k - 1) {
  122. right = index - 1;
  123. index = partition(input, left, right);
  124. } else {
  125. left = index + 1;
  126. index = partition(input, left, right);
  127. }
  128. }
  129. for (int i = 0; i < k; i++) {
  130. result.add(input[i]);
  131. }
  132.  
  133. return result;
  134. }
  135.  
  136. /**
  137. * partition函数
  138. * @param a
  139. * @param left
  140. * @param right
  141. * @return
  142. */
  143. public int partition(int[] a, int left, int right) {
  144. while (left < right) {
  145. while (left < right && a[left] <= a[right]) {
  146. right--;
  147. }
  148. if (left < right) {
  149. swap(a, left, right);
  150. }
  151. while (left < right && a[left] <= a[right]) {
  152. left++;
  153. }
  154. if (left < right) {
  155. swap(a, left, right);
  156. }
  157.  
  158. }
  159. return left;
  160. }
  161.  
  162. public void swap(int[] a, int i, int j) {
  163. int tmp = a[i];
  164. a[i] = a[j];
  165. a[j] = tmp;
  166. }
  167.  
  168. @Test
  169. public void testGetLeastNumbers_Solution() {
  170. int[] a = { 4, 5, 1, 6, 2, 7, 3, 8 };
  171. int k = 4;
  172. ArrayList<Integer> list = GetLeastNumbers_SolutionPartition(a, k);
  173. System.out.println(list.toString());
  174.  
  175. ArrayList<Integer> list2 = GetLeastNumbers_SolutionPriorityQuene(a, k);
  176. System.out.println(list2.toString());
  177.  
  178. ArrayList<Integer> list3 = GetLeastNumbers_SolutionMaxHeap(a, k);
  179. System.out.println(list3.toString());
  180.  
  181. }
  182. }

除了基于优先队列,时间复杂度为O(nlogk)、堆排序,时间复杂度为O(nlogk)、partition函数,时间复杂度为O(n)的解法之外,还有基于冒泡排序的解法时间复杂度为(nk)

求数组中最小的k个数的更多相关文章

  1. 求一个数组中最小的K个数

    方法1:先对数组进行排序,然后遍历前K个数,此时时间复杂度为O(nlgn); 方法2:维护一个容量为K的最大堆(<算法导论>第6章),然后从第K+1个元素开始遍历,和堆中的最大元素比较,如 ...

  2. 【算法】数组与矩阵问题——找到无序数组中最小的k个数

    /** * 找到无序数组中最小的k个数 时间复杂度O(Nlogk) * 过程: * 1.一直维护一个有k个数的大根堆,这个堆代表目前选出来的k个最小的数 * 在堆里的k个元素中堆顶的元素是最小的k个数 ...

  3. [算法]找到无序数组中最小的K个数

    题目: 给定一个无序的整型数组arr,找到其中最小的k个数. 方法一: 将数组排序,排序后的数组的前k个数就是最小的k个数. 时间复杂度:O(nlogn) 方法二: 时间复杂度:O(nlogk) 维护 ...

  4. 《程序员代码面试指南》第八章 数组和矩阵问题 找到无序数组中最小的k 个数

    题目 找到无序数组中最小的k 个数 java代码 package com.lizhouwei.chapter8; /** * @Description: 找到无序数组中最小的k 个数 * @Autho ...

  5. 小米笔试题:无序数组中最小的k个数

    题目描述 链接:https://www.nowcoder.com/questionTerminal/ec2575fb877d41c9a33d9bab2694ba47?source=relative 来 ...

  6. 窥探算法之美妙——寻找数组中最小的K个数&python中巧用最大堆

    原文发表在我的博客主页,转载请注明出处 前言 不论是小算法或者大系统,堆一直是某种场景下程序员比较亲睐的数据结构,而在python中,由于数据结构的极其灵活性,list,tuple, dict在很多情 ...

  7. [剑指offer]数组中最小的K个数,C++实现

    原创博文,转载请注明出处! http://github.com/wanglei5205 http://cnblogs.com/wanglei5205 # 题目 输入n个整数,找出其中最小的K个数.例如 ...

  8. 找到数组中最小的k个数

    /*输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字, 则最小的4个数字是1.2.3.4. 示例 1: 输入:arr = [3,2,1], k = ...

  9. 面试题四十:数组中最小的k个数

    方法一:先排序后寻找前k个数: 方法二:受面试题三十九,寻找超过一半的数的启发,只把里面的middle改成k-1就行: void HalfNum( int [ ] Array ,int k){ int ...

随机推荐

  1. 2018-03-03-解决win下凭据删除不干净而无法登录共项目录的问题

    layout: post title: 2018-03-03-解决win下凭据删除不干净而无法登录共项目录的问题 key: 20180303 tags: GIT 版本管理 modify_date: 2 ...

  2. UVA - 1220 Party at Hali-Bula 树的最大独立集

    题意:  给定n个人,存在上下级关系,每个人只有一个上级,求最大独立集.并判断最大独立集是否唯一 思路:d[i][0]表示以i为根的子树中,不选择第i个节点的最大独立集,f[i][0]表示以i为根的子 ...

  3. java 集合框架(十六)Map

    一.概述 Map是一个包含键值对的集合,一个map不能有重复的键(key),而且每个键至多只能对应一个值.Map同Collection一样,它的所有通用实现都会提供一个转换器构造函数,接收一个Map类 ...

  4. 项目部署到Tomcat报错

    1.今天晚上,我想把dojo项目部署到Tomcat中,结果发现部署不了,Tomcat报错.而且,这个错误白天时也碰到了. 错误具体详细如下: Publishing failed with multip ...

  5. Stanford Word Segmenter使用

    1,下载 Stanford Word Segmenter软件包: Download Stanford Word Segmenter version 2014-06-16 2,在eclipse上建立一个 ...

  6. freemarker报错之一

    freemarker 1.错误描述 java.io.FileNotFoundException: Template user.ftl not found. at freemarker.template ...

  7. 关于TS流的解析

    字节.在TS流里可以填入很多类型的数据,如视频.音频.自定义信息等.他的包的结构为,包头为4个字节,负载为184个字节(这184个字节不一定都是有效数据,有一些可能为填充数据). 工作形式: 因为在T ...

  8. Android中selector的使用

    第一种方法(强烈推荐) 方法:selector做遮罩,原图做background. 我们做按钮的时候经常需要用两个图片来实现按钮点击和普通状态的样式,这就需要提供两种图片,而且每个分辨率下还有多套图片 ...

  9. 【网络流24题22】最长k可重线段集问题

    题面戳我 sol 千万!千万!不要理解错题意了!最长K可重,不是说线段最多K可重!你以为计算几何? 原文:使得在\(x\)轴上的任何一点\(p\),\(S\)中与直线\(x=p\)相交的开线段个数不超 ...

  10. [BZOJ2326] [HNOI2011] 数学作业 (矩阵乘法)

    Description Input Output Sample Input Sample Output HINT Source Solution 递推式长这样:$f[n]=f[n-1]*10^k+n$ ...