最简便的方法是循环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, int j){

本文介绍了在大规模无序数组中寻找最小k个数的两种方法:快速排序和BFPRT算法。快速排序平均时间复杂度为O(N),但最坏情况为O(N^2)。BFPRT利用中位数的中位数策略,确保每次能淘汰3N/10的数据,总时间复杂度为O(N)。文章通过代码解析了这两种算法的实现细节和优化策略。


被折叠的 条评论
为什么被折叠?



