题目:输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
方法一 直接排序
通过对数组排序,可得到最小的K个数,时间复杂度O(N*lgN)
方法二 变异的快排
现在一个哨兵,对两次的进行筛选,大于哨兵的值再右侧,小于哨兵的值在左侧。
如果哨兵的位置index>K,对于[begin ~ index-1]再次快排。
如果哨兵的位置index<K,对于[index+1 ~ end]再次快排。
结果得到的最小的K个数不是有序的。
代码如下
import java.util.ArrayList;
import java.util.Random;
public class Solution {
public static void main(String[] args) {
Solution s = new Solution();
ArrayList<Integer> result = s.GetLeastNumbers_Solution(new int[] { 0,1,1,1,1,1,1,1,5,1,1,0 }, 4);
// ArrayList<Integer> result = s.GetLeastNumbers_Solution(new int[] { 4, 5, 1, 6, 2, 7, 3, 8 }, 6);
System.out.println(result);
}
public ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {
ArrayList<Integer> result = new ArrayList<>();
if (k <= input.length && k > 0) {
quickSort(input, k, 0, input.length - 1);
for (int i = 0; i < k; ++i)
result.add(input[i]);
}
return result;
}
private void quickSort(int[] input, int k, int begin, int end) {
// 终止条件
if (begin >= end) return;
// 选择哨兵
Random random = new Random();
int index = begin + random.nextInt(end - begin);
int tmp = input[index];
int i = begin, j = end;
// 快排
while (i < j) {
while (i < j && input[i] < tmp)
++i;
input[index] = input[i];
index = i;
// 注意是 input[j] >= tmp
while (i < j && input[j] >= tmp)
--j;
input[index] = input[j];
index = j;
}
input[index] = tmp;
if (index == k - 1)
return;
if (index > k - 1) {
quickSort(input, k, begin, index - 1);
} else {
quickSort(input, k, index + 1, end);
}
}
}