剑指offer之面试题30:最小的k个数
来源:互联网 发布:登山鞋知乎 编辑:程序博客网 时间:2024/04/30 10:29
题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
思路:如果不考虑时间效率的话,很容易想到就是把数组排序,直接用Arrays.sort(int[] a)方法可以对指定的 int 型数组按数字升序进行排序(但有一点注意,这样就会修改输入的数组)。该排序算法是一个经过调优的快速排序法,此算法在许多数据集上提供 n*log(n) 性能。排序之后位于前k个数就是最小的k个数。
Note:如果不想修改数组,可以将数组中的值放进ArrayList中,然后用Collections.sort(List<T> list)该排序算法是一个经过修改的合并排序算法(其中,如果低子列表中的最高元素小于高子列表中的最低元素,则忽略合并)。此算法提供可保证的 n log(n) 性能。 此实现将指定列表转储到一个数组中,并对数组进行排序,在重置数组中相应位置处每个元素的列表上进行迭代。这避免了由于试图原地对链接列表进行排序而产生的 n2 log(n) 性能。
代码如下:
import java.util.ArrayList;import java.util.Collections;public class Solution { public static ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) { ArrayList<Integer> list=new ArrayList<Integer>(); //边界处理 if(input==null||input.length<=0||k>input.length||k<=0) return list; //不改变原来的数组,可以把数组值放进list中 for(int i=0;i<input.length;i++){ list.add(input[i]); } //排序 Collections.sort(list); //返回前k个数,即移除后面的数 while(list.size()>k){ list.remove(k); } return list; } public static void main(String[] args){ int[] input={4,5,1,6,2,7,3,8}; System.out.println(GetLeastNumbers_Solution(input,4).toString()); }}
其他解法:基于Partition函数的O(n)解法
题目中只说找出最小的k个数,没说k的数必须有序,所以基于Partition函数的思想,可以令比第k个数字小的在左边,比其大的在右边,这样返回左面的k个数,即可。
代码如下:
import java.util.ArrayList;public class Solution { public static ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) { ArrayList<Integer> list=new ArrayList<Integer>(); //边界处理 if(input==null||input.length<=0||k>input.length||k<=0) return list; int start=0; int end=input.length-1; int index=RandomizedPartition(input,start,end); //第k个数,下标为k-1,使得input[0..k-2]<=input[k-1]<input[k..end-1] while(index!=k-1){ if(index>k-1) index=RandomizedPartition(input,start,index-1); else index=RandomizedPartition(input,index+1,end); } //把前k个数放进list中 for(int i=0;i<k;i++){ list.add(input[i]); } return list; } public static int RandomizedPartition(int[] input, int start, int end) { int temp=(int)(Math.random()*(end - start + 1)) + start; swap(input,temp,end); int i=start-1; for(int j=start;j<end;j++){ if(input[j]<=input[end]){ i++; swap(input,i,j); } } swap(input,i+1,end); return i+1; } public static void swap(int[] array, int k, int end) { int temp=array[k]; array[k]=array[end]; array[end]=temp; } public static void main(String[] args){ int[] input={4,5,1,6,2,7,3,8}; System.out.println(GetLeastNumbers_Solution(input,4).toString()); }}
如果不能修改输入数组,怎么办?
如果不修改输入数组,且又把前k个数保存,只能创建一个k大小的容器用来存放最小的k个数。然后怎么做?
当容器不满时(数字小于k),直接放进容器里。
当容器满时,不能直接放进去,想到可以利用操作系统中页面置换的思想,把已在容器中的不满足最小k个数的数字替换出去,首先替换出去的应该是k个数中最大的(可以排除),当然如果待插入的数字比容器中最大的数字还大,无需替换,直接遍历下一个。
总之,当容器满时需要做3件事:1容器中找到最大数;2有可能删除最大数;3在2的基础上向容器中加入一个新的数。想到最大堆满足在O(1)时间找到最大数,且在O(logk)时间删除和插入。
0 0
- 剑指offer之面试题30:最小的k个数
- 剑指offer之面试题30最小的k个数
- 剑指Offer之面试题30:最小的K个数
- 剑指offer面试题30最小的k个数
- [剑指offer][面试题30]最小的k个数
- 【剑指offer】面试题30:最小的K个数
- 剑指Offer:面试题30 最小的k个数
- 剑指offer:面试题30,求最小的K个数
- 剑指offer 面试题30—最小的k个数
- 剑指offer 面试题30 最小的K个数
- 【剑指Offer学习】【面试题30:最小的k个数】
- 剑指offer-面试题30:最小的K个数
- 剑指Offer----面试题30:最小的K个数
- 剑指offer-----面试题30(最小的k个数)
- 剑指offer面试题30:最小的K个数
- 剑指offer--面试题30:最小的K个数
- 剑指offer-面试题30-最小的k个数
- 剑指Offer系列-面试题30:最小的K个数
- 第六届山东省ACM竞赛 A题 Nias and Tug-of-War
- RE的原因
- 算法竞赛入门经典第四章:部分习题解答
- C++统计字符出现的次数并输出
- Android获取手机的型号和系统版本
- 剑指offer之面试题30:最小的k个数
- Android引导页Splash设计
- Codeforces 165B Burning Midnight Oil 【二分】
- android 获取 imei号码 以及其他手机信息
- maven基本概念
- 第六届山东省ACM竞赛 C题 Game!
- js轮播图原理
- “农田灌溉(Farm Irrigation), ZOJ2412”问题的一种解法
- 网页分享链接