题目描述:输入n 个整数,找出其中最小的K 个数。
方法 一:要求数组中最小的k个数,最容易想到的就是利用冒泡排序的思想,每一轮排序把剩余数组中最小的一个数字放到前面已排序的后面,只要进行K轮即可。
代码实现:
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
if(input == null)
return null;
ArrayList<Integer> list = new ArrayList<Integer>(k);
if(k > input.length)
return list;
int temp;
for(int i = 0; i < k; i++){
for(int j = i + 1; j < input.length; j++){
if(input[i] > input[j]){
temp = input[i];
input[i] = input[j];
input[j] = temp;
}
}
list.add(input[i]);
}
return list;
}
该方法的优点是,思路清晰,易于理解,时间复杂度为O(kn)。缺点就是,时间复杂度大了点,关键是改变了原有的输入数组。
方法二:
- 可以先创建一个大小为k的数据容器来存储最小的k个数字,从输入的n个整数中一个一个读入放入该容器中,如果容器中的数字少于k个,按题目要求直接返回空;
- 如果容器中已有k个数字,而数组中还有值未加入,此时就不能直接插入了,而需要替换容器中的值。按以下步骤进行插入:
- 先找到容器中的最大值;
- 将待查入值和最大值比较,如果待查入值大于容器中的最大值,则直接舍弃这个待查入值即可;如果待查入值小于容器中的最小值,则用这个待查入值替换掉容器中的最大值;
- 重复上述步骤,容器中最后就是整个数组的最小k个数字。
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> list = new ArrayList<>();
if (input == null || k <= 0 || k > input.length) {
return list;
}
int[] kArray = Arrays.copyOfRange(input,0,k);
// 创建大根堆
buildHeap(kArray);
for(int i = k; i < input.length; i++) {
if(input[i] < kArray[0]) {
kArray[0] = input[i];
maxHeap(kArray, 0);
}
}
for (int i = kArray.length - 1; i >= 0; i--) {
list.add(kArray[i]);
}
return list;
}
public void buildHeap(int[] input) {
for (int i = input.length/2 - 1; i >= 0; i--) {
maxHeap(input,i);
}
}
private void maxHeap(int[] array,int i) {
int left=2*i+1;
int right=left+1;
int largest=0;
if(left < array.length && array[left] > array[i])
largest=left;
else
largest=i;
if(right < array.length && array[right] > array[largest])
largest = right;
if(largest != i) {
int temp = array[i];
array[i] = array[largest];
array[largest] = temp;
maxHeap(array, largest);
}
}
也可以利用现有的优先队列PriorityQueue,构造最大堆,如下:
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> result = new ArrayList<>();
if (input.length <= k) {
for (int value : input) {
result.add(value);
}
return result;
}
PriorityQueue<Integer> queue = new PriorityQueue<>(k, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
for (int i = 0; i < input.length; i++) {
if(i >= k) {
Integer number = queue.peek();
if (number > input[i]) {
queue.poll();
queue.add(input[i]);
}
} else {
queue.add(input[i]);
}
}
List<Integer> result2 = queue.stream().collect(Collectors.toList());
result.addAll(result2);
return result;
}