题目链接
题目:
分析:
- 回顾一下快速排序, 快速排序的思想就是找一个基准值key, 按照基准值, 将数组分成两块, 分别是<key和>key的区域,然后继续对这两个区域划分, 那么快速排序的时间复杂度是O(N*logN), 但是如果数组中有许多相同的元素, 如果我们选定的基准值就有相同的元素, 而基准值我们只选定了其中一个, 这样会降低排序的效率
- 所以我们可以按照"将数组分成三块"的思想实现快排, 在处理数据量有很多重复的情况下,效率会大大提升。
- 找基准值时, 我们要选取随机数, 经过大量的计算, 这样效率最高, 那我们可以生成下标, 就相当于生成了数组中的随机数, 我们要生成的随机下标要在我们所排序的下标范围内方法时:
int key = nums[new Random().nextInt(r - l + 1) + l];//l和r表示此时需要排序的左右位置 -
快速排序算法主要流程:a. 定义递归出口;b. 利⽤随机选择基准函数⽣成⼀个基准元素;c. 利⽤荷兰国旗思想将数组划分成三个区域;d. 递归处理左边区域和右边区域。
代码:
class Solution {
public int[] sortArray(int[] nums) {
qsort(nums, 0, nums.length - 1);
return nums;
}
public void qsort(int[] nums, int l, int r) {
if (l >= r)
return;
int key = nums[new Random().nextInt(r - l + 1) + l];
int left = l - 1;
int right = r + 1;
int i = l;
while (i < right) {
if (nums[i] < key) {
swap(nums, i++, ++left);
} else if (nums[i] == key) {
i++;
} else {
swap(nums, i, --right);
}
}
qsort(nums, l, left);
qsort(nums, right, r);
}
public void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}