最简便的方法是循环K次,依次找出最小的,第2小的,第K小的值,时间复杂度O(N*K),这种方法使用于K比较小的时候,如个位数,如果N数据量很大,K也较大,不适用。因为K大于N时,时间复杂度变成O(N^2)。
第二种是堆排序,建立一个大根堆,时间复杂度是O(NlogK),此方法博客中有写到,详见堆排序。
一、用快速排序,随机取枢轴量可以做到平均时间复杂度O(N),但是值选的不好会退化到O(N^2)
/**
* Created by Administrator on 2018/2/4 0004.
* 用快速排序,随机取枢轴量可以做到平均时间复杂度O(N),但是值选的不好会退化到O(N^2)
*/
public class Main {
public static void main(String[] args) {
//int[] arr = {6,9,1,3,1,2,2};
int[] arr = { 6, 9, 1, 3, 1, 2, 2, 5, 6, 1, 3, 5, 9, 7, 2, 5, 6, 1, 9 };
int k = 10;
System.out.println(Arrays.toString(getMinKNums(arr, k)));
}
public static int[] getMinKNums(int[] arr, int k){
int[] res = new int[k];
getKnumsHelp(arr, 0, arr.length-1, k, res, 0);
return res;
}
public static void getKnumsHelp(int[] arr, int start, int end, int k, int[] res, int index){
if (index == k){
return;
}
int x = arr[start];
int left = start-1, right = end + 1, i = start;
while (i < right){
if (arr[i] < x){
++left;
swap(arr, left, i);
++i;
}
else if (arr[i] > x){
--right;
swap(arr, right, i);
}
else {
++i;
}
}
if (right - start == k){
for (int j = 0; j < k; j++) {
res[index + j] = arr[start + j];
}
}
else if (right - start < k){
for (int j = 0; j < right- start; j++) {
res[index + j] = arr[start + j];
}
getKnumsHelp(arr, right, end, k-(right-start), res, index + right -start);
}
else {
getKnumsHelp(arr, start, right-2, k, res, index); //特别注意此处 right-1是key处,证明right-1... start的元素个数大于k,所以下标是从right-1的前面一个位置开始,如果改成right-1就是这这个例子中死循环了
}
}
public static void swap(int[] arr, int i,