当前位置:首页 > 科技  > 软件

如何利用快排的小技巧,解决算法难题?

来源: 责编: 时间:2023-10-10 18:32:08 220观看
导读快速排序采用的是分治思想,即在一个无序的序列中选取一个任意的基准元素pivot,利用pivot将待排序的序列分成两部分,前面部分元素均小于或等于基准元素,后面部分均大于或等于基准元素,然后采用递归的方法分别对前后两部分重

快速排序采用的是分治思想,即在一个无序的序列中选取一个任意的基准元素pivot,利用pivot将待排序的序列分成两部分,前面部分元素均小于或等于基准元素,后面部分均大于或等于基准元素,然后采用递归的方法分别对前后两部分重复上述操作,直到将无序序列排列成有序序列。Qt328资讯网——每日最新资讯28at.com

今天就为大家带来面试中经常出现排序算法的深度解析。Qt328资讯网——每日最新资讯28at.com

快速排序本质上是一个前序遍历

上一篇文章中讲到,合并排序本质上和二叉树后续遍历非常类似,而快速排序本质上和二叉树的前序遍历非常类似。Qt328资讯网——每日最新资讯28at.com

首先你还先回忆一下二叉树的前序遍历:Qt328资讯网——每日最新资讯28at.com

// 递归function preOrder(root, array = []) {  if (root === null) return null;  array.push(root.val);  postOrder(root.left, array);  postOrder(root.right, array);}

这里可以将代码拆分为三部分:Qt328资讯网——每日最新资讯28at.com

// 边界处理if (root === null) return null;
// 根节点信息处理array.push(root.val);
// 根节点的信息,传递给左右子树。postOrder(root.left, array);postOrder(root.right, array);

边界处理先不提,二叉树的前序遍历,有两个重点的特点:Qt328资讯网——每日最新资讯28at.com

  • 根节点的信息;
  • 根节点的信息,传递给左右子树。

简单利用伪代码表示就是:Qt328资讯网——每日最新资讯28at.com

function 前序遍历():    获取根节点信息;    将根节点的信息传递左右子树/左右子数组;

快速排序和前序遍历类似,这个伪代码对于快速排序同样成立。Qt328资讯网——每日最新资讯28at.com

并且对于排序算法来说,排序也就意味着有序,有序性就是信息,因此,我们要做的事情就是把能拿到的有序信息,传递给左子数组和右子数组。Qt328资讯网——每日最新资讯28at.com

有序性

那在排序算法中,如果利用有序性了? 其实有序性的就是选择一个数 X,并且利用这个数,将数组分成三部分:Qt328资讯网——每日最新资讯28at.com

  • 小于 X 的部分;
  • 等于 X 的部分;
  • 大于 X 的部分;

左右子树/子数组的处理

对于到二叉树来说,小于 X 的部分也就是二叉树的左子树,等于 X 的部分就是二叉树的根节点,大于 X 的部分就是二叉树的右子树。Qt328资讯网——每日最新资讯28at.com

二叉树对于子树的处理,就是利用递归的方式来进行处理。Qt328资讯网——每日最新资讯28at.com

postOrder(root.left);postOrder(root.right);

排序算法对于子数组的处理,同样也是递归地处理左子数组和右子数组。 相对于二叉树的前序遍历来说,快速排序的左右子区间是由切分动态生成的,并不像二叉树那样由指针固定。并且对于根结点的处理,需要执行“三路切分”操作,将一个数组切分为三段;Qt328资讯网——每日最新资讯28at.com

所以总结一下,又讲回到前面的伪代码:Qt328资讯网——每日最新资讯28at.com

function 前序遍历/快速排序():    获取根节点信息;    将根节点的信息传递左右子树/左右子数组;

并且前序遍历/快速排序的特点可以总结为以下 3 点:Qt328资讯网——每日最新资讯28at.com

  • 划分子结构
  • 根节点的信息处理
  • 将根节点的信息,传递给左右子树/左右子数组。

1. 划分子结构

对于二叉树而言,子树的划分是天然的,已经在数据结构里面约定好了,比如 Node.left、Node.right。Qt328资讯网——每日最新资讯28at.com

root.leftroot.right 可以直接通过树的子节点拿

但是对于数组而言,划分子结构,也就是找一个节点,将数组切分为几份,切分的时候,如果想到达最优的效率,那么将数组切为平均的两半效率应该是最高的(可以联想到二叉平衡树的效率)。但是快排不能保证选择一个数,就一定能将数组切分成为两半,所以它有自己特殊的处理。Qt328资讯网——每日最新资讯28at.com

利用 x 将数组分为三份左子数组 = [小于 x 的部分] = [b, l)根节点 = [等于 x 的部分] = [l, i)右子数组 = [大于 x 的部分] = [i, e)

2. 根节点的信息处理

对于二叉树来说,根节点就是当前节点,也节点的处理也即是收集节点信息。Qt328资讯网——每日最新资讯28at.com

node// 根节点信息处理array.push(root.val);

而排序算法的"根节点"也就是选择的元素,并且排序算法会通过划分的子结构和选中的元素来进行排序处理也就是上面说的特殊处理;对于排序算法来说,"根节点"和划分子结构息息相关。Qt328资讯网——每日最新资讯28at.com

if (a[i] < x) {    // 小于 x 的部分} else if (a[i] === x) {    // 等于 x 的部分} else {    // 大于 x 的部分}

3. 将根节点的信息,传递给左右子树/左右子数组

二叉树前序遍历好说,通过递归的方式处理左右子树。Qt328资讯网——每日最新资讯28at.com

// 二叉树的前序遍历拿左右子树的信息preOrder(root.left);preOrder(root.right);

而排序算法需要分别对左子数组和右子数组进行排序,那么类似的对子数组的排序应该也只需要递归就可以了。Qt328资讯网——每日最新资讯28at.com

// 快速排序去拿左右子数组的信息qsort(a, b, l);qsort(a, i, e);

最后,不管是二叉树还是快速排序都要考虑一下边界:Qt328资讯网——每日最新资讯28at.com

二叉树的边界就是节点不能为空。Qt328资讯网——每日最新资讯28at.com

if (root === null) return null;

快速排序的边界就是:Qt328资讯网——每日最新资讯28at.com

  • 当 b >= e,说明这个区间是一个空区间,没有必要再排序;
  • 当 b + 1 === e,说明只有一个元素,也没有必要排序。
if (b > e || b + 1 >= e) {  return;}

小结

对于二叉树来说,代码相对比较简单。Qt328资讯网——每日最新资讯28at.com

function preOrder(root, array = []) {  // 边界处理  if (root === null) return null;  // 第一步:划分子结构,二叉树在结构上已经划分了子结构 root.left、root.right 可以直接通过树的子节点拿  // 第二步:根节点的信息处理  array.push(root.val)  // 第三步:将根节点的信息,传递给左右子树/左右子数组(递归的方式)  postOrder(root.left, array);  postOrder(root.right, array);}

对于快速排序来说,如何划分子结构?如何到达最优的效率?都是在写算法时需要注意的。Qt328资讯网——每日最新资讯28at.com

// 交换数组中两个元素的值 function swap(A, i, j) {  const t = A[i];  A[i] = A[j];  A[j] = t;}function qsort(a, begin, end) {    // 边界情况   if (b > e || b + 1 >= e) {     return    } /*********************核心代码****************************/ // 第一步:划分子结构    const mid = b + ((end - begin) >> 1); // 第二步:获取根节点信息 x const x = a[mid]; // 根据 x 将数组一分为三 【三路切分】 let l = begin; let i = begin; let r = end - 1;    while(i < r) {        if (a[i] < x) {            // 小于 x 的部分            swap(a, l++, i++);        } else if (a[i] === x) {            // 等于 x 的部分            i++;        } else {            // 大于 x 的部分            swap(a, r--, i);        }    } // 第三步:将根节点的信息传递左右子子树 qsort(a, b, l); qsort(a, i, e); /*********************核心代码****************************/}// 主函数,将数组nums排序 function quickSort(nums) {  if (nums == null)    return;  qsort(nums, 0, nums.length);}

这里可以思考一下,为什么我们在节点排序处理是通过 swap 操作?它和时间复杂度和空间复杂度有什么关系?Qt328资讯网——每日最新资讯28at.com

while(i < r) {    if (a[i] < x) {        // 小于 x 的部分        swap(a, l++, i++);    } else if (a[i] === x) {        // 等于 x 的部分        i++;    } else {        // 大于 x 的部分        swap(a, r--, i);    }}

总结

通过合并排序和快速排序,可以得出结论,数组其实是另外一种形式的二叉树,只不过有时候需要我们动态地把左/右子树给切分出来,不同的切分方式,可以解决不同的问题。大家也可以自己思考和尝试,看看还能不能发现更多排序的特点和巧妙用法,并且将它们总结下来。欢迎大家一起在评论区交流。Qt328资讯网——每日最新资讯28at.com

参考

  • https://leetcode.cn/problems/median-of-two-sorted-arrays/solutions/258842/xun-zhao-liang-ge-you-xu-shu-zu-de-zhong-wei-s-114/
  • https://kaiwu.lagou.com/course/courseInfo.htm?courseId=685#/detail/pc?id=6697

本文链接:http://www.28at.com/showinfo-26-12744-0.html如何利用快排的小技巧,解决算法难题?

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 豁然开朗:这问题我不信你能分析的这么透彻!

下一篇: 面试中如何答好:CAS

标签:
  • 热门焦点
  • K60至尊版刚预热 一加Ace2 Pro正面硬刚

    K60至尊版刚预热 一加Ace2 Pro正面硬刚

    Redmi这边刚如火如荼的宣传了K60 Ultra的各种技术和硬件配置,作为竞品的一加也坐不住了。一加中国区总裁李杰发布了两条微博,表示在自家的一加Ace2上早就已经采用了和PixelWo
  • 线程通讯的三种方法!通俗易懂

    线程通讯的三种方法!通俗易懂

    线程通信是指多个线程之间通过某种机制进行协调和交互,例如,线程等待和通知机制就是线程通讯的主要手段之一。 在 Java 中,线程等待和通知的实现手段有以下几种方式:Object 类下
  • 三言两语说透柯里化和反柯里化

    三言两语说透柯里化和反柯里化

    JavaScript中的柯里化(Currying)和反柯里化(Uncurrying)是两种很有用的技术,可以帮助我们写出更加优雅、泛用的函数。本文将首先介绍柯里化和反柯里化的概念、实现原理和应用
  • 使用Webdriver-manager解决浏览器与驱动不匹配所带来自动化无法执行的问题

    使用Webdriver-manager解决浏览器与驱动不匹配所带来自动化无法执行的问题

    1、前言在我们使用 Selenium 进行 UI 自动化测试时,常常会因为浏览器驱动与浏览器版本不匹配,而导致自动化测试无法执行,需要手动去下载对应的驱动版本,并替换原有的驱动,可能还
  • 电视息屏休眠仍有网络上传 爱奇艺被质疑“薅消费者羊毛”

    电视息屏休眠仍有网络上传 爱奇艺被质疑“薅消费者羊毛”

    记者丨宁晓敏 见习生丨汗青出品丨鳌头财经(theSankei) 前不久,爱奇艺发布了一份亮眼的一季报,不仅营收和会员营收创造历史最佳表现,其运营利润也连续6个月实现增长。自去年年初
  • 2天涨粉255万,又一赛道在抖音爆火

    2天涨粉255万,又一赛道在抖音爆火

    来源:运营研究社作者 | 张知白编辑 | 杨佩汶设计 | 晏谈梦洁这个暑期,旅游赛道彻底火了:有的「地方」火了&mdash;&mdash;贵州村超旅游收入 1 个月超过 12 亿;有的「博主」火了&m
  • 本地生活这块肥肉,拼多多也想吃一口

    本地生活这块肥肉,拼多多也想吃一口

    出品/壹览商业 作者/李彦编辑/木鱼拼多多也看上本地生活这块蛋糕了。近期,拼多多在App首页&ldquo;充值中心&rdquo;入口上线了本机生活界面。壹览商业发现,该界面目前主要
  • DRAM存储器10月价格下跌,NAND闪存本月价格与上月持平

    DRAM存储器10月价格下跌,NAND闪存本月价格与上月持平

    10月30日,据韩国媒体消息,自今年年初以来一直在上涨的 DRAM 存储器的交易价格仅在本月就下跌了近 10%,此次是全年首次降价,而NAND 闪存本月价格与上月持平。市
  • “买真退假” 这种“羊毛”不能薅

    “买真退假” 这种“羊毛”不能薅

    □ 法治日报 记者 王春   □ 本报通讯员 胡佳丽  2020年初,还在上大学的小东加入了一个大学生兼职QQ群。群主&ldquo;七王&rdquo;在群里介绍一些刷单赚
Top