快速排序也是使用分治策略,用partition函数将序列一分为二(O(n))后,将子序列递归排序((1 / n) * ∑[T(k) + T(n - k - 1)]),最后合并有序子序列(O(1)),T(n) = O(n) + (1 / n) * ∑[T(k) + T(n - k - 1)] = O(n * logn)。
一、快速排序
1、快速排序的实现
public static void quickSortCore(int[] arr, int lo, int hi) {
if (lo < hi) {
int mid = partition(arr, lo, hi);
quickSortCore(arr, lo, mid - 1);
quickSortCore(arr, mid + 1, hi);
}
} 2、partition的实现
public static int partition(int[] arr, int lo, int hi) {
// 令arr[hi]为pivot
// 将原数组分为小于pivot、pivot和大于等于pivot三部分
swap(arr, lo + (int) Math.random() * (hi - lo + 1), hi);
int small = lo - 1;
while (lo < hi) {
if (arr[lo] < arr[hi]) {
swap(arr, ++small, lo++);
} else {
lo++;
}
}
swap(arr, ++small, hi);
return small;
} 3、源码
二、剑指offer[40]
最小的k个数 题解
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4
快排的partition函数会将原序列分为左右两个子序列,左边序列都小于pivot,右边序列都大于或等于pivot,当pivot为数组的第k个元素时,数组中pivot及其之前的元素都小于右边序列,即为n个整数中最小的k个数。
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
if (input == null || input.length == 0 || input.length < k || k == 0) {
return new ArrayList<>();
}
// 在数组中寻找位置为k - 1的pivot
int start = 0, end = input.length - 1;
int index = partition(input, start, end);
while (index != k - 1) {
if (index < k - 1) {
start = index + 1;
} else {
end = index - 1;
}
index = partition(input, start, end);
}
// 收集这k个数
ArrayList<Integer> res = new ArrayList<>();
for (int i = 0; i <= index; i++) {
res.add(input[i]);
}
return res;
} 上述解法并不是本题的最优解,但可作为快速排序partition的应用。最优解见题解。

京公网安备 11010502036488号