leetcodeT912-快排优化-三路划分

简介: leetcodeT912-快排优化-三路划分

1.前言

因为快排的名声太大

并且快排在某些场景下比较慢,所以leetcode"修理"了一下快排

特意设计了一些专门针对快排的测试用例

所以用快排过不了这一题

2.为什么需要三路划分的优化?

我们遇到了第一个为难快排的测试用例全是重复值2

我们发现快排在遇到全是重复值的数据时,

这里以左右指针法为例

每次右指针从右向左找小时都要跑到左指针位置处

然后进行交换,递归

每次都只能把那个重复数据2放到当前递归区间的起始位置,就像是冒泡排序一样每次只能冒一个数到对应位置,但是冒泡排序好歹还能有一个优化(没有发生数据交换时即为有序,排序结束),可是这时快排连优化都没有

退化到了O(n^2)的时间复杂度

3.三路划分的思想及举例画图

这是整个过程,大家也可以自己对照三种情况画一下

一趟三路划分

前:

后:

我们发现:

一趟三路划分后整个数组被分为三个部分:

假设区间左端点:begin,右端点:end

[begin,l-1]:这一段上区间的值小于key

[l,r] :这一段上区间的值等于key

[r+1,end]:这一段上区间的值大于key

等于key的那一段区间不需要递归了,因为它们已经位于它们该在的地方了

接下来只需要递归[begin,l-1],[r+1,end]即可

4.三路划分的代码实现

//三路划分
void QuickSort(int* a, int begin, int end)
{
  if(begin>=end)
    {
        return;
    }
    int keyIndex=GetMidIndex(a,begin,end);
    Swap(&a[begin],&a[keyIndex]);
    int key=a[begin];
    int left=begin,right=end,cur=begin+1;
    while(cur<=right)
    {
        if(a[cur]<key)
        {
            Swap(&a[cur],&a[left]);
            cur++;
            left++;
        }
        else if(a[cur]==key)
        {
            cur++;
        }
        else
        {
            Swap(&a[cur],&a[right]);
            right--;
        }
    }
    QuickSort(a,begin,left-1);
    QuickSort(a,right+1,end);
}

所以我们可以发现,三路划分之后,数组中重复越多,我们快排就越快

因为重复值直接就跳过了

对于那个测试用例来说

第一趟排序之后left还是等于begin,right还是等于end

所以再往下递归就会触发begin>=end这个条件,就会直接返回

所以达到了O(n)的时间复杂度

所以对于这个测试用例来说已经比较快了

5.三数取中修改

但是:

尽管我们通过了所有的测试用例,但是因为耗时太长leetcode直接针对快排

那么怎么办,怎么过呢?

我们去掉三数取中优化,看一下是哪个测试用例对我们的针对

这里我们打印了一下数组开头,中间,结尾的那三个数

这个题目最大值是50000,

这个测试用例最大值是上万,而我们三数取中取出来的是7500,相对来说偏小了

所以我们要对三数取中的mid搞一个随机数

只需要在三数取中的代码中给mid一个随机值即可

这里设置随机数种子,避免出现rand函数产生的重复值不变的情况

尽管我们过是过了,但是Leetcode这一题的测试用例太针对快排了

所以快排被欺负的很惨

以上就是leetcodeT912针对快排的三路划分优化的讲解,希望能对大家有所帮助!

相关文章
|
7月前
|
算法 JavaScript Java
【状态压缩】【动态规划】【C++算法】1125.最小的必要团队
【状态压缩】【动态规划】【C++算法】1125.最小的必要团队
|
算法
快排三种递归及其优化,非递归和三路划分
快排三种递归及其优化,非递归和三路划分
68 0
|
人工智能 算法
【算法分析与设计】递归与分治策略(二)
【算法分析与设计】递归与分治策略
|
算法
建筑抢修 (大根堆+贪心+优先队列+快速排序+2重思想比较)
建筑抢修 (大根堆+贪心+优先队列+快速排序+2重思想比较)
52 0
|
7月前
【错题集-编程题】不相邻取数(动态规划 - 线性 dp)
【错题集-编程题】不相邻取数(动态规划 - 线性 dp)
|
7月前
|
算法 测试技术 C#
【广度优先搜索】【堆】【C++算法】407. 接雨水 II
【广度优先搜索】【堆】【C++算法】407. 接雨水 II
|
机器学习/深度学习 算法 编译器
【算法分析与设计】递归与分治策略(一)
【算法分析与设计】递归与分治策略
|
7月前
|
算法 测试技术 C#
【树 图论 阶乘 组合 深度优先搜索】1916. 统计为蚁群构筑房间的不同顺序
【树 图论 阶乘 组合 深度优先搜索】1916. 统计为蚁群构筑房间的不同顺序
|
7月前
|
存储 算法 Java
【算法设计与分析】— —实现最优载的贪心算法
【算法设计与分析】— —实现最优载的贪心算法
|
搜索推荐
“掌握更多的快速排序技巧:三路划分、双路快排和非递归的深入理解”(上)
“掌握更多的快速排序技巧:三路划分、双路快排和非递归的深入理解”(上)
184 0