力扣精选算法100道——排序数组(分治快排)

本文介绍了如何在快速排序中使用随机化选择基准值,以避免最坏情况的发生。通过在给定区间内均匀随机选取基准值,对`sortArray`函数和`qsort`子函数进行详细解释,展示了如何在C++中实现这一优化的快速排序算法。
摘要由CSDN通过智能技术生成

目录

🚩了解题意

🚩算法原理

🎈取随机值

🎈c++中取随机数的步骤

🚩代码实现



🚩了解题意

本题的题意很简单,就是将nums数组排成升序即可。

🚩算法原理

本题和颜色分类那个题目很相似,就是从小到大排序。只不过不同的是,这次不是取nums[i]和左右指针相比较了,本题用的是key关键字,而关键字是随机的,不是特定的哪个值。依旧利用的是三种判断思路。

  • 如果nums[i]<key,先让left++,然后与nums[i]和nums[left]交换位置,然后i++。
  • 如果nums[i]>key,先让--right,然后与nums[i]和nums[right]交换位置。(i不往后,nums[i]依旧是未知数字)
  • 如果nums[i]==key i++. 
  • 最后i和right相遇结束
        while(i<right){
            if(nums[i]<key)swap(nums[++left],nums[i++]);
            else if(nums[i]==key)i++;
            else swap(nums[--right],nums[i]);
        }

分治快排思想,每次key进行划分,<key和>key进行划分,<key再进行划分,>key也进行划分。

🎈取随机值

在快速排序算法中,为了提高算法的性能和避免出现最坏情况(即当输入数组已经有序时造成快速排序的时间复杂度退化为O(n^2)),经常会使用随机化来选择基准值。选择随机基准值可以降低出现最坏情况的概率,使得快速排序在平均情况下表现更好。

在给定区间 [left, right] 中随机选择基准值时,通过 nums[r%(right-left+1)+left] 的方式可以保证基准值在该区间内是均匀随机选择的,即基准值可以是区间内的任意一个元素,而不是固定选择区间的第一个、最后一个或中间值,从而使得算法更具随机性,降低了最坏情况发生的概率。

nums[r%(right-left+1)+left] 是一个用于在给定范围 [left, right] 内随机选择基准值的方法。让我解释一下这个表达式是如何计算的:

  1. (right - left + 1):计算给定范围内元素的数量,即区间长度。
  2. r % (right - left + 1):生成一个 [0, right - left] 之间的随机数,通过取余操作符 % 可以确保生成的随机数在这个范围内。
  3. r % (right - left + 1) + left:将上一步生成的随机数平移至 [left, right] 区间内,即加上 left 的值,从而确保基准值在给定区间内。(因为后面的分治,[right,nums.size()-1]区间中随机值需要+left,否则就不再这个区间了。

因此,表达式 nums[r%(right-left+1)+left] 可以通过这种方式在闭区间 [left, right] 内均匀随机选择一个元素作为基准值。

🎈c++中取随机数的步骤

1/设置随机种子:在程序的开头使用 srand(time(NULL)); 设定随机数种子,以确保每次运行程序时生成的随机数不同。
2/生成随机数:
使用 rand() 函数来生成一个伪随机数,比如 int randomNumber = rand();

按照逻辑依次走一遍。 

然后我们用分治

从上述的遍历后我们分成了三个部分

  • <key  [l,left]
  • =key [left+1,right-1]
  • >key [right,r]

然后我们要进行分治 

[l,left]区域继续进行一次快排操作

[right,r]区域继续进行一次快排操作

 然后继续调用这个函数<key的区域,然后调用>key的区域,每次分治后的key都是随机取的。


🚩代码实现

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        srand(time(NULL));//种下一颗随机数种子
        qsort(nums,0,nums.size()-1);
        return nums;
    }
    //快排
    void qsort(vector<int>&nums,int l,int r){
        if(l>=r)return;

        int key=getRandom(nums,l,r);
        int i=l,left=l-1,right=r+1;
        while(i<right){
            if(nums[i]<key)swap(nums[++left],nums[i++]);
            else if(nums[i]==key)i++;
            else swap(nums[--right],nums[i]);
        }
        //[l,left] [left+1,right-1] [right,r]
        qsort(nums,l,left);
        qsort(nums,right,r);
    }
    int getRandom(vector<int>&nums,int left,int right){
        int r=rand();
        return nums[r%(right-left+1)+left];
    }
};

做好自己。

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值