题目
输入n个整数,找出其中最小的k个数。
例如
输入4,5,1,6,2,7,3,8
输出1,2,3,4
思路
思路一
排序后取出前k个数。时间复杂度为O(nlgn)
思路二
依然根据快速排序中交换数据的方法,被选取的数字被交换的位置,该位置前面的数都比被选取的小,该位置后面的都比选取的大,所以只要找到第k个位置就好。代码见下。
时间复杂度O(n)
思路三
我们可以先创建一个k个容量的容器,每次读取一个数字,如果该容器没满,就将该数组放进容器。如果该容器已满,则得到该容器中的最大值,如果读取的数字大于等于最大值,则读取下一个数字,否则,删除最大值,将读取的数组放进容器,所有数字读取完毕后容器中的K个数字为最小。
需要思考,怎样得到k个容器中的最大值以及删除插入的操作的复杂度,选用合适的数据结构使得复杂度最小。
可以用最大堆,得到最大值的复杂度为O(1),删除和插入数字的复杂度为O(lgK),java中封装好的PriorityQueue即可使用。
也可以使用红黑树,得到最大值,删除,插入的复杂度都为O(lgk)
总的时间复杂度为O(nlgk).
代码见下。
代码
思路二
public static int[] getLeastNumbers(int[] numbers,int length,int k){ if(numbers == null || length <= 0 || k <= 0 || k > length)return null;
int[] result = new int[k];
int start = 0;
int end = length - 1;
int index = partition(numbers,start,end);
while(index != k){
if(index < k){
start = index + 1;
index = partition(numbers,start,end);
} else{
end = index - 1;
index = partition(numbers,start,end);
}
}
for(int i = 0;i < k;i++){
result[i] = numbers[i];
}
return result;
}
public static int partition(int[] numbers,int start,int end){
while(start < end) {
while (numbers[end] >= numbers[start] && start < end) end--;
int temp = numbers[end];
numbers[end] = numbers[start];
numbers[start] = temp;
while (numbers[end] >= numbers[start] && start < end) start++;
temp = numbers[end];
numbers[end] = numbers[start];
numbers[start] = temp;
}
return start;
}
思路三
public static int[] getLeastNumbers2(int[] numbers,int length,int k){ if(numbers == null || length <= 0 || k <= 0 || k > length)return null; PriorityQueue<Integer> result = new PriorityQueue<>(k, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o2.compareTo(o1); } }); int[] results = new int[k]; for(int i = 0;i < k;i++){ result.offer(numbers[i]); } for(int i = k;i < length;i++){ int max = result.peek(); if(numbers[i] < max){ result.poll(); result.offer(numbers[i]); } } for(int i = 0;i < k;i++){ int max = result.poll(); results[i] = max; } return results; }
总结
思路一最直观,但是时间复杂度相对较高。
思路二时间复杂度最低,但是需要修改输入的数组。
思路三需要用到最大堆或者红黑树,需要对数据结构掌握熟悉,但是特别适合处理海量数据,因为可以一个一个处理数据。