文章目录

  • 思考
  • 前言
  • 如何分析一个排序算法?
    • 排序算法的执行效率
    • 排序算法的内存消耗
    • 排序算法的稳定性
  • 如何选择合适的排序算法?
  • 如何优化快速排序?
  • 解答思考题
  • 参考链接

思考

  • 为什么插入排序比冒泡排序更受欢迎?
  • 如何用快排思想在O(n)内查找第K大元素?
  • 如何根据年龄给100万用户数据排序?(线性排序)
  • 如何实现一个通用的、高性能的排序函数?(排序优化)

前言

我最近在系统整理一些 Java 后台方面的面试题和参考答案,有找工作需求的童鞋,欢迎关注我的 Github 仓库,如果觉得不错可以点个 star 关注 :

  • 1、awesome-java-interview
  • 2、awesome-java-notes

如何分析一个排序算法?

是否原地排序 是否稳定 最好、最坏、平均时间复杂度 空间复杂度 是否基于比较
冒泡排序 O(n)、 O(n^2)、 O(n^2) O(1)
插入排序 O(n)、 O(n^2)、 O(n^2) O(1)
选择排序 O(n^2)、 O(n2)、O(n2) O(1)
希尔排序 O(n)、O(n2)、O(n1.3) O(1)
快速排序 O(nlogn)、O(n^2)、O(nlogn) O(logn)~O(n)
归并排序 O(nlogn)、O(nlogn)、O(nlogn) O(n)
计数排序 O(n+k)、O(n+k)、O(n+k),k 是数据范围 O(n+k)
桶排序 O(n)、O(n)、O(n) O(N+M),N表示待排数据个数,M表示桶个数
基数排序 O(nk)、O(nk)、O(n*k),k 是维度 O(n+k)
堆排序 O(nlogn)、O(nlogn)、O(nlogn) O(1)

排序算法的执行效率

  • 1、最好情况、最坏情况、平均情况时间复杂度
  • 2、时间复杂度的系数、常数 、低阶
    • 时间复杂度反映数据规模 n 很大时的一个增长趋势,常忽略系数、常数、低阶
    • 实际软件开发中,数据规模可能比较小,比较同一阶时间复杂度的排序算法时,不能忽略系数、常数、低阶
  • 3、比较次数和交换(或移动)次数
    • 基于比较的算法会涉及两种操作:元素比较大小、元素交换或移动
    • 分析排序算法执行效率时,应该要考虑比较次数(或移动)次数

排序算法的内存消耗

  • 原地排序(Sorted in place):特指空间复杂度为 O(1) 的排序算法
  • 算法的内存消耗可以通过空间复杂度来衡量

排序算法的稳定性

  • 稳定的排序算法: 指待排序的序列中存在值相等的元素时,经过排序后,相等元素之间原有的先后顺序不变

如何选择合适的排序算法?

  • 对小规模数据进行排序,可以选择时间复杂度是 O(n^2) 的算法
  • 对大规模数据进行排序,时间复杂度是 O(nlogn) 的算法更加高效
  • 为了兼顾任意规模数据的排序,一般都会首选时间复杂度是 O(nlogn) 的排序算法来实现排序函数

如何优化快速排序?

  • 快速排序出现 O(n^2)时间复杂度的主要原因是因为分区节点选择不够合理
  • 最理想的分区节点是:被分区点分开的两个分区中,数据的数量差不多
  • 方法
    • 1、三数取中法(五数取中、十数取中等):从区间的首、尾、中间,分别取出一个数,然后对比大小,取这 3 个数的中间值作为分区点
    • 2、随机法:每次从要排序的区间中,随机选择一个元素作为分区点
    • 3、等等

解答思考题

  • 1. 为什么插入排序比冒泡排序更受欢迎?

    从代码实现上来看,冒泡排序的数据交换要比插入排序的数据移动要复杂,冒泡排序需要 3 个赋值操作,而插入排序只需要 1 个。

     // 冒泡排序中数据的交换操作:if (a[j] > a[j+1]) {  //  交换int tmp = a[j];a[j] = a[j+1];a[j+1] = tmp;flag = true;}//  插入排序中数据的移动操作:if (a[j] > value) {a[j+1] = a[j];  //  数据移动} else {break;}
    
  • 2. 如何用快排思想在O(n)内查找第K大元素?

    比如,4, 2, 5, 12, 3 这样一组数据,第 3 大元素就是 4。

    我们选择数组区间 A[0…n-1] 的最后一个元素 A[n-1] 作为 pivot,对数组 A[0…n-1] 原地分区,这样数组就分成了三部分,A[0…p-1]、A[p]、A[p+1…n-1]。

    如果 p+1=K,那 A[p] 就是要求解的元素;如果 K>p+1, 说明第 K 大元素出现在 A[p+1…n-1] 区间,我们再按照上面的思路递归地在 A[p+1…n-1] 这个区间内查找。同理,如果 K<p+1,那我们就在 A[0…p-1] 区间查找。

    我们再来看,为什么上述解决思路的时间复杂度是 O(n)?

    第一次分区查找,我们需要对大小为 n 的数组执行分区操作,需要遍历 n 个元素。第二次分区查找,我们只需要对大小为 n/2 的数组执行分区操作,需要遍历 n/2 个元素。依次类推,分区遍历元素的个数分别为、n/2、n/4、n/8、n/16.……直到区间缩小为 1。

    如果我们把每次分区遍历的元素个数加起来,就是:n+n/2+n/4+n/8+…+1。这是一个等比数列求和,最后的和等于 2n-1。所以,上述解决思路的时间复杂度就为 O(n)。

  • 3. 如何根据年龄给100万用户数据排序?(线性排序)

    假设年龄的范围最小 1 岁,最大不超过 120 岁。可以遍历这 100 万用户,根据年龄将其划分到这 120 个桶里,然后依次顺序遍历这 120 个桶中的元素。这样就得到了按照年龄排序的 100 万用户数据。

  • 4. 如何实现一个通用的、高性能的排序函数?(排序优化)

    1.数据量不大时,可以采取用时间换空间的思路
    2.数据量大时,优化快排分区点的选择
    3.防止堆栈溢出,可以选择在堆上手动模拟调用栈解决
    4.在排序区间中,当元素个数小于某个常数是,可以考虑使用O(n^2)级别的插入排序
    5.用哨兵简化代码,每次排序都减少一次判断,尽可能把性能优化到极致

参考链接

  • 《数据结构与算法之美》专栏 王争

常见排序算法的最好、最坏、平均时间复杂度以及空间复杂度相关推荐

  1. 常见排序算法及其对应的时间复杂度、空间复杂度

    常见排序算法及其对应的时间复杂度.空间复杂度: 排序算法经过长时间演变,大体可以分为两类:内排序和外排序.在排序过程中,全部记录存放在内存,则成为内排序:如果排序过程中需要使用外存,则称为外排序,本文 ...

  2. 常见排序算法的时间复杂度、空间复杂度、稳定性比较

    常见排序算法的时间空间复杂度.稳定性比较 一.排序算法比较 注: 1.归并排序可以通过手摇算法将空间复杂度降到O(1),但是时间复杂度会提高. 2. 基数排序时间复杂度为O(N*M),其中N为数据个数 ...

  3. 详细分析冒泡排序、选择排序、插入排序(最好/最坏/平均时间复杂度(有序度)、稳定性、内存消耗(原地排序))

    如何分析排序算法 最好.最坏.平均时间复杂度 算法的时间复杂度,会随着排序集合的有序性而改变.我们需要分析不同算法在不同数据下的表现 最好时间复杂度:在完全有序的情况下的时间复杂度(满有序度) 最坏时 ...

  4. 常见排序算法及对应的时间复杂度和空间复杂度

    排序算法经过了很长时间的演变,产生了很多种不同的方法.对于初学者来说,对它们进行整理便于理解记忆显得很重要.每种算法都有它特定的使用场合,很难通用.因此,我们很有必要对所有常见的排序算法进行归纳. 排 ...

  5. python实现常见排序算法

    python实现常见排序算法 快速排序 思想:取出第一个元素把它放到序列的中间某一个正确位置,以它进行分割成左边和右边,再分别对左边和右边进行取元素分割(递归) 递归实现 def quicksort( ...

  6. 十种常见排序算法欢聚一堂

    文章目录 1.常见排序算法分类 2.非线性时间比较类排序 2.1 交换类排序 2.1.1 冒泡排序 2.1.2 快速排序 2.2 插入类排序 2.2.1 直接插入排序 2.2.2 Shell 排序 2 ...

  7. Java常见排序算法之插入排序

    一.概述 本节由小千给大家分享Java常见排序算法之插入排序,之前我们说过排序是算法中的一部分.所以我们学习排序也是算法的入门,为了能让大家感受到排序是算法的一部分,我举个例子证明一下:比如麻将游戏, ...

  8. php 版本排序,四种常见排序算法--PHP版本

    1.冒泡排序法 /** * 冒泡排序 * des 对一组数据,比较相邻数据的大小,将值小数据在前面,值大的数据放在后面. */ $array = [2,5,1,3,7,4]; $result = bu ...

  9. 常见排序算法_解释的算法-它们是什么以及常见的排序算法

    常见排序算法 In its most basic form, an algorithm is a set of detailed step-by-step instructions to comple ...

  10. ++代码实现 感知机的原理_常见排序算法原理及JS代码实现

    来源:SegmentFault 思否社区 作者:Warren 本文只是将作者学习的过程以及算法理解进行简单的分享,提供多一个角度的理解说明,或许让你的困惑能得以解决(代码或说明若有问题,欢迎留言.联系 ...

最新文章

  1. PHP RSA签名
  2. Hive 基础(1):分区、桶、Sort Merge Bucket Join
  3. java正则转义_Java 正则表达式 转义字符
  4. 企业中的微服务:敌是友?
  5. 【C#学习笔记】使用C#中的Dispatcher
  6. Python3安装(Windows)
  7. java--复制文件的方法:
  8. 给大学生的劝告,你们为何应该开始接触 Unix/Linux
  9. nodejs菜鸟教程
  10. 希尔伯特矩阵(Hilbert matrix)
  11. 清华大学建筑学计算机,建筑专业十强大学排名:清华第一,第四堪称黑马
  12. java如何设置控制台打印的字体颜色、背景、字体样式(idea设置打印字体样式)工具类 - 附插件方式
  13. CSP 201809 第二题 买菜
  14. ps安装了可以打开但开始里面找不到_黑苹果安装入门(hackintosh install)
  15. 联系超级计算机,与超级计算机共事是一种怎样的体验?
  16. 裁剪rplidar的扫描数据
  17. First name, Middle name, Last name
  18. Linux下如何颁发证书:学习使用openssl搭建一个CA
  19. 计算机仿真技术-基于matlab的电子信息类课程课后答案,计算机仿真技术——基于MATLAB的电子信息类课程(第3版)...
  20. 什么是划分子网?网络工程师划分子网有啥技巧?

热门文章

  1. 解决UDP出现的10054错误
  2. YumRepo Error: All mirror URLs are not using ftp, http[s] or file解决办法
  3. JDK14打包工具jpackage的使用
  4. Java的Socket网络编程
  5. MSYS+MinGW64环境的搭建
  6. 步进电机驱动器的作用
  7. 如何写CV和Cover Letter
  8. 俞敏洪大学经典励志演讲:像树一样活着
  9. Lora SX1278芯片 模块引脚的功能介绍
  10. flashback使用