public class Demo {
public static void main(String[] args) {
int[] a = { 6, 0, 5, 4, 7, 2, 1 };
// int[] a = { 0, 1, 2, 4, 5, 6, 7 };
// int[] a = { 7, 6, 5, 4, 2, 1, 0 };
print(a);
// 求第K大元素
int k = 3;
int kthLarge = kthLarge(a, k);
System.out.println("kthLarge=" + kthLarge);
// 快速排序
quickSort(a);
print(a);
}
/************************** 求第K大元素 ********************************/
public static int kthLarge(int[] a, int k) {
if (a == null || a.length < k) {
return -1;
}
/*
* 解题原理:
* 1. 将数组从大到小原地分区,分成三部分,A[0...p-1]、A[p]、A[p+1...n-1];左边逗比A[p]大,右边都比A[p]小
* 2. 分区之后:
* - 如果 p+1 = k,那么A[p]就是要求的元素;
* - 如果 p+1 < k,那么A[p]就落在[p + 1] 到 [n - 1]区间;反之则落在[0] 到 [p - 1] 区间
*/
int p = partition0(a, 0, a.length - 1);
while (p + 1 != k) {
if (p + 1 < k) {
p = partition0(a, p + 1, a.length - 1);
} else {
p = partition0(a, 0, p - 1);
}
}
return a[p];
}
/************************** 快速排序 ********************************/
// 快速排序
static void quickSort(int[] a) {
quickSort0(a, 0, a.length - 1);
}
static void quickSort0(int[] a, int l, int r) {
if (l >= r) {
return;
}
// 升序
int p = partition(a, l, r);
// 降序
// int p = partition0(a, l, r);
quickSort0(a, l, p - 1);
quickSort0(a, p + 1, r);
}
// 获取分区点(降序)
static int partition(int[] a, int l, int r) {
int p = a[r];
// 比p小的序列
int i = l;
// 从整个数组中,遍历获取比p小的序列放到l~i中
for (int j = l; j < r; ++j) {
if (a[j] < p) {
if (i == j) {
++i;
} else {
int tmp = a[i];
a[i++] = a[j];
a[j] = tmp;
}
}
}
a[r] = a[i];
a[i] = p;
return i;
}
// 获取分区点(升序)
static int partition0(int[] a, int l, int r) {
int p = a[r];
// 比p小的序列
int i = l;
// 从整个数组中,遍历获取比p小的序列放到l~i中
for (int j = l; j < r; ++j) {
if (a[j] > p) {
if (i == j) {
++i;
} else {
int tmp = a[i];
a[i++] = a[j];
a[j] = tmp;
}
}
}
a[r] = a[i];
a[i] = p;
return i;
}
/************************** 打印 ********************************/
static void print(int[] a) {
StringBuilder s = new StringBuilder();
for (int i : a) {
if (s.length() == 0) {
s.append(i);
} else {
s.append(",").append(i);
}
}
System.out.println(s.toString());
}
}