Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package shz.core.alg.search;
import static shz.core.ArrayHelp.swap;
public final class TopK {
private TopK() {
throw new IllegalStateException();
}
/**
* bfprt查找第k小值
* 时间复杂度 O(n)
*/
public static int bfprt(int[] a, int k) {
if (k <= 1) {
int min = 0;
for (int i = 1; i < a.length; ++i) if (a[i] < a[min]) min = i;
return a[min];
}
return bfprt(a, 0, a.length - 1, k);
}
private static int bfprt(int[] a, int lo, int hi, int k) {
if (lo == hi) return a[lo];
int lt = -1, i = lo, gt = hi;
//这里选取中位数为快排的基准值
int v = median(a, lo, hi);
//标记指针 i 是否第一次遇到 v
boolean mark = false;
while (i <= gt) {
if (a[i] < v) {
if (mark) swap(a, lt++, i);
++i;
} else if (a[i] > v) swap(a, i, gt--);
else {
if (!mark) {
mark = true;
//初始lt
lt = i;
}
++i;
}
}
//a[lo...lt-1] < v = a[lt...gt] < a[gt+1...hi]
if (lo + k - 1 >= lt) {
if (lo + k - 1 <= gt) return a[lt];
return bfprt(a, gt + 1, hi, k + lo - gt - 1);
}
return bfprt(a, lo, lt - 1, k);
}
private static int median(int[] a, int lo, int hi) {
int n = hi - lo + 1;
int[] medians = new int[n / 5 + (n % 5 == 0 ? 0 : 1)];
int i = 0, j = lo + 4;
for (; j < hi; j += 5) medians[i++] = mid(a, j - 4, j);
medians[i] = mid(a, j - 4, hi);
//获取中位数的中位数
return bfprt(medians, 0, medians.length - 1, medians.length / 2);
}
/**
* 取中位数
*/
private static int mid(int[] a, int lo, int hi) {
//插入排序
int min = lo;
for (int i = lo + 1; i <= hi; ++i) if (a[i] < a[min]) min = i;
swap(a, lo, min);
for (int i = lo + 2; i <= hi; ++i) for (int j = i; a[j] < a[j - 1]; --j) swap(a, j, j - 1);
return a[lo + (hi - lo) / 2];
}
}