例题:排序数组
以力扣912题为例:
给你一个整数数组 nums,请你将该数组升序排列。
快速排序法
class Solution {
public int[] sortArray(int[] nums) {
randomizedQuicksort(nums, 0, nums.length - 1);
return nums;
}
public void randomizedQuicksort(int[] nums, int l, int r) {
if (l < r) {
// 随机选择主元,即划分数组为两份的中间位置
int pos = randomizedPartition(nums, l, r);
// 左边排序
randomizedQuicksort(nums, l, pos - 1);
// 右边排序
randomizedQuicksort(nums, pos + 1, r);
}
}
public int randomizedPartition(int[] nums, int l, int r) {
// 套路1:随机选一个作为我们的主元,并右置
int i = new Random().nextInt(r - l + 1) + l;
swap(nums, r, i);
// 计算主元
return partition(nums, l, r);
}
public int partition(int[] nums, int l, int r) {
int pivot = nums[r];
// 套路2:维护两个指针(快慢指针)
// 初始时指针分别为-1和0
// 慢指针为i,总是指向小于主元的最后位置
// 快指针为j,总是指向大于主元的最后位置
int i = l - 1;
for (int j = l; j <= r - 1; ++j) {
if (nums[j] <= pivot) {
// 当小于主元的情况时,有两种情况
// (1)i==j,swap都不改变
// (2)i<j,swap交换i+1和j的元素,此时i+1就时大于主元的第一个位置(慢指针为i,总是指向小于主元的最后位置)
i = i + 1;
swap(nums, i, j);
}
}
// 把右置的主元返回中间,即与大于主元的第一个位置的元素交换
// 这样以主元为界,左右区域总是小于/大于主元
swap(nums, i + 1, r);
// 返回主元位置
return i + 1;
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
评论区