前言:
答案:a, i + 1, r, k - (i - l + 1)
首先分享一篇讲快速排序的,讲的可好了!浅显易懂,值得一看~
快速排序
一份有注释的代码:
public class Demo5 {
// 以下代码可以从数组a[]中找出第k小的元素。
public static int quickSelect(int a[], int l, int r, int k) {
// 1、随机选择一个元素作为基准元素(此时选择的基准元素为x)
Random rand = new Random();
int p = rand.nextInt(r - l + 1) + l;
int x = a[p];
// 这里令我们随机选择的元素a[p]与数组最右端的元素a[r]互换
int tmp = a[p];
a[p] = a[r];
a[r] = tmp;
// 2、相当于设置两个指针i和j,i为左指针,j为右指针,它们分别指向数组最左和最右的元素
int i = l, j = r;
while (i < j) {
//3、将左指针指向的元素与基准元素相比较,如果左指针指向的元素小于基准元素,则左指针向右移动一位
while (i < j && a[i] < x)
i++;
//4、通过上一步的移动,左指针左边的元素全部比基准元素小,令数组最右的元素(此时的数组最右的元素等于基准元素x)等于此时左指针指向的元素,右指针向左移动一位,此时的a[j]大于等于x
if (i < j) {
a[j] = a[i];
j--;
}
//5、将右指针指向的元素与基准元素相比较,如果右指针指向的元素大于基准元素,则右指针向左移动一位
while (i < j && a[j] > x)
j--;
//6、通过上一步的移动,右指针右边的元素全部比基准元素大,令左指针指向的元素等于此时右指针指向的元素,左指针向右移动一位,此时的a[i]小于等于x
if (i < j) {
a[i] = a[j];
i++;
}
}
//7、通过步骤3、4、5、6后,可以确定a[i]的位置就是我们选择的基准元素排序后应该所在的位置
a[i] = x;
//8、令基准元素位置的索引i等于p
p = i;
//9、通过算式i - l + 1得到的是在数组中第几小的元素,若它等于k,则得到题目要求的数组a[]中第k小的元素
if (i - l + 1 == k)
return a[i];
//若小于k,即我们所求的元素在i的右边,此时左指针指向的元素为a[p+1],右指针指向的元素依旧是a[r],所求第k小的元素变为第k - (i - l + 1)小
if (i - l + 1 < k)
return quickSelect(a, i + 1, r, k - (i - l + 1)); // 填空
else
//若大于k,即我们所求的元素在i的左边,此时左指针指向的元素为认为a[l],右指针指向的元素为a[i-1],仍旧是求第k小的元素
return quickSelect(a, l, i - 1, k);
}
public static void main(String args[]) {
int[] a = { 1, 4, 2, 8, 5, 7 };
System.out.println(quickSelect(a, 0, 5, 4));
}
}