面试题30.最小的K个数
原创
©著作权归作者所有:来自51CTO博客作者mb6304a73bed12a的原创作品,请联系作者获取转载授权,否则将追究法律责任
面试题30.最小的K个数
题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
思路1:
排序,然后取出前k个数字。这种方法的时间复杂度是O(nlogn)
思路2:
利用Partition算法,首先在数组中随机选择一个数字,然后把比它小的数字移到它的左边,把比它大的数字移到右边。全部移动完后:
- 如果这个数字刚好处于第k个位置,那么它就是第k个数。
- 如果这个数字在第k个位置的右边,说明第k个数在它左边,继续对左边查找
- 如果这个数字在第k个位置的左边,说木第k个数在它右边,继续对右边查找
思路3:
针对海量数据,可以使用堆排序的方法。
构建一个大顶堆,用k个数字初始化堆。然后对于后面的数字,与堆顶比较
- 如果小于堆顶,则与堆顶替换,向下调整堆。
- 反之,这个数肯定不是最小的k个数,跳过这个数
思路4:
利用java的TreeMap来实现,统计数字出现的次数,然后从小到大找到第k个数。
下面是思路1和思路4的代码
import java.util.*;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {
ArrayList<Integer> arr = new ArrayList<>();
if(k > input.length || k < 1) {
return arr;
}
// 解法1 排序 然后取前k个 O(nlogn)
/*Arrays.sort(input);
for(int i = 0; i < k; i++) {
arr.add(input[i]);
}*/
// 解法4 使用红黑树 增删改查O(logk)
TreeMap<Integer, Integer> treeMap = new TreeMap<>();
for(Integer i : input) {
if(treeMap.keySet().contains(i)) {
treeMap.put(i, treeMap.get(i) + 1);
}else {
treeMap.put(i, 1);
}
}
for(Integer i : treeMap.keySet()) {
int n = treeMap.get(i);
for(int j = 0; j < n; j++) {
arr.add(i);
k--;
if(k <= 0) return arr;
}
}
return arr;
}
}