leetcodeT912-快排优化-三路划分

这篇具有很好参考价值的文章主要介绍了leetcodeT912-快排优化-三路划分。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.前言

leetcodeT912-快排优化-三路划分,数据结构与算法,算法,leetcode,排序算法
因为快排的名声太大
并且快排在某些场景下比较慢,所以leetcode"修理"了一下快排
特意设计了一些专门针对快排的测试用例
所以用快排过不了这一题

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

我们遇到了第一个为难快排的测试用例全是重复值2
我们发现快排在遇到全是重复值的数据时,

这里以左右指针法为例
每次右指针从右向左找小时都要跑到左指针位置处
然后进行交换,递归

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

退化到了O(n^2)的时间复杂度
leetcodeT912-快排优化-三路划分,数据结构与算法,算法,leetcode,排序算法

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

leetcodeT912-快排优化-三路划分,数据结构与算法,算法,leetcode,排序算法
这是整个过程,大家也可以自己对照三种情况画一下
leetcodeT912-快排优化-三路划分,数据结构与算法,算法,leetcode,排序算法
一趟三路划分
前:
leetcodeT912-快排优化-三路划分,数据结构与算法,算法,leetcode,排序算法
后:
leetcodeT912-快排优化-三路划分,数据结构与算法,算法,leetcode,排序算法

我们发现:
一趟三路划分后整个数组被分为三个部分:
假设区间左端点:begin,右端点:end
[begin,l-1]:这一段上区间的值小于key
[l,r] :这一段上区间的值等于key
[r+1,end]:这一段上区间的值大于key

等于key的那一段区间不需要递归了,因为它们已经位于它们该在的地方了
接下来只需要递归[begin,l-1],[r+1,end]即可

4.三路划分的代码实现

leetcodeT912-快排优化-三路划分,数据结构与算法,算法,leetcode,排序算法

//三路划分
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)的时间复杂度
所以对于这个测试用例来说已经比较快了
leetcodeT912-快排优化-三路划分,数据结构与算法,算法,leetcode,排序算法

5.三数取中修改

但是:
leetcodeT912-快排优化-三路划分,数据结构与算法,算法,leetcode,排序算法
尽管我们通过了所有的测试用例,但是因为耗时太长leetcode直接针对快排
那么怎么办,怎么过呢?

我们去掉三数取中优化,看一下是哪个测试用例对我们的针对
这里我们打印了一下数组开头,中间,结尾的那三个数
leetcodeT912-快排优化-三路划分,数据结构与算法,算法,leetcode,排序算法
这个题目最大值是50000,
这个测试用例最大值是上万,而我们三数取中取出来的是7500,相对来说偏小了

所以我们要对三数取中的mid搞一个随机数
只需要在三数取中的代码中给mid一个随机值即可
leetcodeT912-快排优化-三路划分,数据结构与算法,算法,leetcode,排序算法
这里设置随机数种子,避免出现rand函数产生的重复值不变的情况
leetcodeT912-快排优化-三路划分,数据结构与算法,算法,leetcode,排序算法
尽管我们过是过了,但是Leetcode这一题的测试用例太针对快排了
所以快排被欺负的很惨
leetcodeT912-快排优化-三路划分,数据结构与算法,算法,leetcode,排序算法

以上就是leetcodeT912针对快排的三路划分优化的讲解,希望能对大家有所帮助!文章来源地址https://www.toymoban.com/news/detail-721210.html

到了这里,关于leetcodeT912-快排优化-三路划分的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构排序——详解快排及其优化和冒泡排序(c语言实现、附有图片与动图示意)

    上次讲了选择排序和堆排序:数据结构排序——选择排序与堆排序 今天就来快排和冒泡 快速排序(Quick Sort)是一种常用的排序算法,它是由英国计算机科学家Tony Hoare于1959年发明的。快速排序的基本思想是通过分治的策略将一个数组分成两个子数组,然后分别对这两个子数

    2024年01月25日
    浏览(44)
  • 全网最全的快速排序方法--Hoare快排 挖坑法快排 二路快排 三路快排 非递归快排

    目录 一.快速排序 1.基本介绍 2.基本思想 二.Hoare快排 0.前情知识 1.交换数组中的两个元素 2.指定范围的插入排序 1.基本思路 2.代码实现 3.优化思路 三.挖坑法快排(校招中适用) 1.基本思路 2.代码实现 四.二路快排 1.基本思路 2.代码实现 3.优化思路 五.三路快排 1.基本思路 2.代码

    2023年04月21日
    浏览(44)
  • 三路快排Java版(带思路分析)

    这里我们直接开始讲相对的最优解 带随机数的三路快排 好了,中间还有很多版本的快排,但是都有一些问题导致在某种极端情况下造成耗费时间极多。 基础快排:在 序列本身有序 的情况下复杂度为O(n²) 带随机数的快排:在 序列本身有序 的情况下复杂度为O(nlogn),但

    2024年02月06日
    浏览(34)
  • 三路快排(基于三指针单趟排序的快速排序)+快排时间复杂度再分析

    目录  一.前言 二. 三路快排 😍算法思想: 😍算法实现步骤: 😍三指针单趟排序的实现:​ 😍非递归快排完全体: 🤔与C标准库里的快排进行对比测试: 三.快排时间复杂度再分析 http://t.csdn.cn/mz8dg http://t.csdn.cn/mz8dg http://t.csdn.cn/1TqDp http://t.csdn.cn/1TqDp 😄关于快排的基本思想和实

    2023年04月15日
    浏览(45)
  • 数据结构——快排与归并

    重要的事说三遍! 学习!学习!学习! 努力!努力!努力! 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为: 任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列

    2024年02月08日
    浏览(46)
  • 【数据结构】快排的详细讲解

    江河入海,知识涌动,这是我参与江海计划的第7篇。 目录:         快排是排序算法中效率是比较高的,快排的基本思想是运用二分思想,与二叉树的前序遍历类似,将数据划分,每次划分确定1个基准值(就是已经确定好有序后位置的数据),以升序为例,基准值左面的数据

    2024年02月06日
    浏览(91)
  • 数据结构与算法-选择&冒泡&快排&计数

        一:选择排序     场景:找出一个班上身高最高的人你会怎么找?A B C D A B 选择排序的思路和插入排序非常相似,也分已排序和未排序区间。但选择排序每次会从未排序区间中找到最小的元素,将其放到已排序区间的末尾。但是不像插入排序会移动数组 选择排序会每次

    2024年02月09日
    浏览(43)
  • 【数据结构】排序之交换排序(冒泡 | 快排)

    在之前的博客中介绍了插入排序,有需要的可以点这个链接: link,这次来介绍交换排序,包括冒泡和快排。 话不多说,正文开始。 基本思想 :所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置。 交换排序的特点是:将键值较大的记录向序

    2024年02月03日
    浏览(39)
  • 【C语言】【数据结构初阶】 快排变慢排?怎么个事儿?

    我们知道,快排是一种很好的排序算法。但是在 极少数 的一些情况下,“快速排序”好像名不副实了。 当数据量非常大,且递归深度太深,有栈溢出的风险。 这样,我们就得到了一个很可惜的结论:快排不是万金油。 但是,这是指的 递归版本 的快排,我们可以写 非递归

    2024年02月17日
    浏览(54)
  • 【数据结构】带你玩转排序:堆排序、希尔排序、插入排序、选择排序、冒泡排序、快排(多版本)、归并排序

    英杰社区 https://bbs.csdn.net/topics/617804998 目录 常见算法的实现         插入排序         希尔排序         堆排序         选择排序         冒泡排序         快速排序         Hoare版本         随机选Keyi               三数取中         挖坑法  

    2024年02月08日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包