剑指offer(二十九)——最小的K个数
题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
题解
一解:
对数组进行排序,使用set进行去重,输出前K个数。
- 至于排序方法,可以自己写,也可以直接用API,排序方法影响时间复杂度。
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> resultList = new ArrayList<>();
Set<Integer> set = new HashSet<Integer>();
Arrays.sort(input);
for(int i = 0; i < input.length; i++) {
set.add(input[i]);
}
if (k > set.size()) {
return resultList;
}
Iterator<Integer> it = set.iterator();
while(k-- != 0) {
resultList.add(it.next());
}
return resultList;
}
二解:
第二种解法是使用最大堆,先压入K个数,再用堆顶的最大值进行比较,替换更小值,最后剩下来的K个数就是最小的了。
- 实测堆会去重,所以不用担心重复数的问题。
- 另一个值得注意的地方是堆并不会排序,所以遍历最大堆出来的元素并不一定有序,但堆顶肯定是最大值。就用了一个笨办法,用栈将堆一个个弹出,然后再存回数组。
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> resultList = new ArrayList<>();
if (k > input.length || k == 0) {
return resultList;
}
PriorityQueue<Integer> minqueue = new PriorityQueue<Integer>(k, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
for(int i = 0; i < input.length; i++) {
if (minqueue.size() != k) {
minqueue.offer(input[i]);
}else if (input[i] < minqueue.peek()) {
minqueue.poll();
minqueue.offer(input[i]);
}
}
Stack<Integer> stack = new Stack<>();
while(minqueue.size() != 0) {
stack.add(minqueue.poll());
}
while(stack.size() != 0) {
resultList.add(stack.pop());
}
return resultList;
}