快排版本1:最差O(n^2) 划分值很偏
总拿最后一个数做划分,划分好最后一个数和大于区的第一个数做交换,然后在小于等于5区域和大于5区域继续往复循环操作,都取各自的最后一个数作为基准数。
快排版本2:最差O(n^2) 划分值很偏
每次排序都能搞定一堆等于5的区域。只要最后一个数和大于区的第一个数做交换
然后左右侧以最后一个数作为基准数,继续做递归。
快排 【最好情况 几乎在中点】O(n*logn)
L到R随机选个数和最后位置做交换,拿最后位置做划分。
举例
L和R的索引分别是10和15
partition后就返回12和13,表示的是划分值区域的左边界和右边界
public int[] sortArray(int[] nums) {
if(nums == null || nums.length < 2){
return nums;
}
quickSort(nums,0,nums.length - 1);
return nums;
}
//交换位置
public void swap(int[] nums,int L,int R){
int temp = 0;
temp = nums[L];
nums[L] = nums[R];
nums[R] = temp;
}
// 快排
public void quickSort(int[] arr,int L,int R){
if(L < R){
// *精华!随机数和最后一个数做交换 随机数:0 <= r < 1
swap(arr,L + (int)(Math.random() * (R - L + 1)),R);
// 拿L和R范围上 以及我选出来的最后一个位置上 做partition
// 返回数组长度一定是2,中间排好序的左边界和右边界
int[] p = partition(arr,L,R);
// p[0]是等于区域的左边界,p[0]-1就是小于区域右边界
quickSort(arr,L,p[0]-1);
// p[1]是等于区域的右边界,p[1]+1就是大于区域左边界
quickSort(arr,p[1]+1,R);
}
}
public int[] partition(int[] arr,int L,int R){
// <区右边界
int less = L - 1;
// <区左边界
int more = R;
// arr[L]表示当前数的位置 还没碰上右边界的第一个数 排序
while(L < more){
if(arr[L] < arr[R]){
swap(arr,++less,L++);
}else if(arr[L] > arr[R]){
// >区左扩
swap(arr,--more,L);
}else{
L++;
}
}
// 都做完后,最后一个数和大于区第一个做交换
swap(arr,more,R);
// 返回中间排好序的左边界和右边界
return new int[] {less + 1,more};
}