1. 题⽬链接:912.排序数组
2. 题⽬描述:
3. 解法(数组分三块思想+随机选择基准元素的快速排序):
算法思路:
我们在数据结构阶段学习的快速排序的思想可以知道,快排最核⼼的⼀步就是Partition(分割数 据):将数据按照⼀个标准,分成左右两部分。
如果我们使⽤荷兰国旗问题的思想,将数组划分为左中右三部分:左边是⽐基准元素⼩的数据, 中间是与基准元素相同的数据,右边是⽐基准元素⼤的数据。然后再去递归的排序左边部分和右边 部分即可(可以舍去⼤量的中间部分)。
在处理数据量有很多重复的情况下,效率会⼤⼤提升。
算法流程:
随机选择基准算法流程:
函数设计:int randomKey(vector& nums, int left, int right)
a. 在主函数那⾥种⼀颗随机数种⼦;
b. 在随机选择基准函数这⾥⽣成⼀个随机数;
c. 由于我们要随机产⽣⼀个基准,因此可以将随机数转换成随机下标:让随机数%上区间⼤⼩, 然后加上区间的左边界即可。
快速排序算法主要流程:
a. 定义递归出⼝;
b. 利⽤随机选择基准函数⽣成⼀个基准元素;
c. 利⽤荷兰国旗思想将数组划分成三个区域;
d. 递归处理左边区域和右边区域。
C++算法代码:
class Solution
{
public:
//快排
void qsort(vector<int>& nums,int l,int r)
{
if(l>=r)
{
return;
}
//取随机关键字
int key=nums[rand()%(r-l+1)+l];
//数据分三块
小于 等于 大于
int left=l-1,right=r+1,i=l;
while(i<right)
{
if(nums[i]<key)
{
swap(nums[i++],nums[++left]);
}
//大于的数据交换后有可能还不符合条件,所以不能i++
else if(nums[i]>key)
{
swap(nums[i],nums[--right]);
}
else
{
i++;
}
}
//小于的部分排序
qsort(nums,l,left);
//大于的部分排序
qsort(nums,right,r);
}
vector<int> sortArray(vector<int>& nums)
{
//种随机数种子
srand(time(NULL));
qsort(nums,0,nums.size()-1);
return nums;
}
};
Java算法代码:
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, right = r + 1, i = l;
while (i < right)
{
if (nums[i] < key) swap(nums, ++left, i++);
else if (nums[i] == key) i++;
else swap(nums, --right, i);
}
// [l, left] [left + 1, right - 1] [rigth, r]
qsort(nums, l, left);
qsort(nums, right, r);
}
public void swap(int[] nums, int i, int j)
{
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
}