题目链接
题目解析
将数组进行升序排序
算法原理
快速排序
先选择基准元素, 然后把数组分成俩部分, 基准左边都是<=key,右边就是>=key.
然后左右区间再重复上述操作
partation
但是里面有元素重复的话, 时间复杂度会退化, 因此我们分成三块
1. 我们用数组分三块的思想, 实现快排, 中间的元素(=key)的不需要处理, <key和>key的需要处理
定义i,left,right,i用来遍历
因此可以分为四块[0,left] 小于key,[left+1,i-1]等于k, [i,right-1] 未扫描 ,[right,n-1] 大于key
分类讨论
nums[i] < key -> 把当前元素加到左边的区域 swap(nums[++left],nums[i++])
nums[i] = key ->i++
nums[i]>key -> 把当前元素加到右边的区域 swap(nums[--right,nums[i])
然后进行递归
数组分三块这个操作是怎么让效率更高?
数组都是重复元素的话, 数组只会执行一次, 因为等于Key
优化:
选择基准元素的方法=> 用随机的方式选择基准元素, left+一个偏移量就是在这个数组上随机取值
代码编写
int key = nums[new Random().nextInt(r - l + 1) + l]; 这个里面就是取基准值为[l,r]区间的随机数
class Solution {
//交换
private static void swap(int[] nums, int index1, int index2) {
int tmp = nums[index1];
nums[index1] = nums[index2];
nums[index2] = tmp;
}
//递归,分三段
private static void quickSort(int[] nums, int l, int r) {
if (l > r) {//处理边界情况, l>r=>这个就是递归的出口
return;
}
//l,r是用来固定左右端点的
int left = l - 1;
int right = r + 1;
int key = nums[new Random().nextInt(r - l + 1) + l];//这个是保证区间是在[l,r]区间里面随机取一个中间值
int i = l;//从区间的开始进行遍历
while (i < right) {
//如果是>key
if (nums[i] < key) {
swap(nums, ++left, i++);
} else if (nums[i] == key) {
//如果是=key
i++;
} else {
//如果是<key
swap(nums, --right, i);
}
}
//处理左区间
quickSort(nums, l, left);
//处理右区间
quickSort(nums, right, r);
}
public int[] sortArray(int[] nums) {
quickSort(nums, 0, nums.length - 1);
return nums;
}
}