思路同75、颜色分类,将整个数组分为三段,小于aa,等于aa,大于aa,其中aa是在数组中随机取的一个数。
1、设置两个指针,l记录第一个非小于aa的位置,l左边比aa小,r记录最后一个非大于aa的位置,r右边比aa大。然后使用i从头到尾扫一遍,nums[i]遇到比aa小的数就和nums[l]互换,遇到比aa大的数就和nums[r]互换,遇到aa就跳过,直到i>r停止(i要将nums[r])处理完。
2、当处理完时:[0,left)-->比aa小的数; [left,right]-->aa; (right,n-1]-->比aa大的数。继续对[0,left), 和(right,n-1]两段采用同样的方法排序。
需要注意的是:
(1)当遇到比aa大的数,换回来的可能是比aa小的数(或者aa),i不能前进,因为如果比aa小,l在i前面,i前面会有aa,要继续交换;
(2)当遇到比aa小的数,换回来的一定是aa(除非i==l,这个时候相当于原地不动),无论哪种情况,i都要前进。
由此该数组分为4段:[0,left)-->比aa小的数; [left,i)-->aa; [i,right]-->乱序; (right,n-1]-->比aa大的数。
void mysort(vector<int>& nums, int first, int last){
if(first>=last) return;
int x=first+rand() % (last-first+1), aa=nums[x], l=first, r=last, i=first;
while(i<=r){
if(nums[i]>aa){
swap(nums[i], nums[r]);
--r;
}
else if(nums[i]==aa) ++i;
else{
swap(nums[i], nums[l]);
++i;
++l;
}
}
mysort(nums, first, l-1);
mysort(nums, r+1, last);
}