热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

时间复杂度_排序算法线性时间复杂度

篇首语:本文由编程笔记#小编为大家整理,主要介绍了排序算法-线性时间复杂度相关的知识,希望对你有一定的参考价值。  一说到排序算法,大部分人都会说

篇首语:本文由编程笔记#小编为大家整理,主要介绍了排序算法-线性时间复杂度相关的知识,希望对你有一定的参考价值。


    一说到排序算法,大部分人都会说出著名的万金油-快速排序、大数据分而治之-归并排序、大数据排名-堆排序。这些排序无论在面试还是实际项目中,都是经常用到的一些排序算法,其平均时间复杂度都在 O(N • log2N),那今天我们就来介绍几种 O(N)的排序算法。

    1,计数排序,输入 n 个范围在 0-k 区间的元素,当 !k >> n 时,排序的运行时间为 O(N)

          论点:对于输入的任一的元素 x,如果有 s 个元素小于,则元素 x 就可以放在 s+1 的位置上,这个时间复杂度近乎 O(1),我们仅需要得出对于每个元素有多少个小于的元素的列表即可在很短的时间内排序完成。

          a.对原数组进行遍历,计算每个元素出现的次数,时间复杂度 O(N),空间复杂度 O(K)

            原数组

            技术图片

 

     额外记录表,下标为元素,值代表出现的次数技术图片

         b,将记录的数组进行计算整理,数组中每个值代表小于当前下标的元素个数,时间复杂度O(K)

额外记录表,下标为元素,值代表小于当前下标的元素个数

技术图片

 

         c.遍历原数组,并按最初提出的论点,进行最终的排序放置到最终数组,并更新记录表中的数值(v-1),时间复杂度O(N) * O(1),空间复杂度O(N)

技术图片

 

         综上所述,所需要的时间复杂度为O(N) + O(K) + O(N)*O(1) = O(N + K),当元素的取值范围较小时,可以达到 O(N)的时间复杂度,空间复杂度为O(N) + O(K) = O(N)

    2,基数排序,建立在计数排序(发现两种排序的谐音完全一样^_^)的基础上,所以请耐心阅读上一段的流程。

          论点:在实际项目过程中,我们需要排序的元素通常很难是在极小范围,这里我们可以利用位数的分隔,首先对所有数值的个位数进行计数排序,以此类推对十位、百位、千位。可以预见我们仅需要对当前元素组进行最大元素的位数次计数排序即可

                     假定最大元素为 x,则进行的计数排序个数为 r = ceil(ln(x)) 取上整数,每次计数排序的时间复杂度为 O(N + K) = O(N + 10) 整个算法复杂度为 ceil(ln(x)) * O(N + 10),所以当最大一位的位数不会超过 ln(N),则整个排序算法的复杂度为 常数 * O(N + 10) = O(N),这种排序算法一般已经可以应用         到很多项目场景中了,只是因为其编码的复杂度和现代计算机的 cpu 性能提高,所以除非巨量的数据排序,否则一般还是会采用快速排序

技术图片

 

    3,桶排序,与基数排序是相反的思路,先生成 n 个相同大小的子区间(桶),将所有元素分到所属的桶内,并按插入排序的方式,放入所属的桶里,时刻保证每个桶内部的数据是有序的。

          论点:只要数据处于散列数据,可以预见每个桶的数据不会太多,除非极端情况下,但只要保证桶的个数,同样可以保证算法的线性时间复杂度(这里先不谈这种情况,这种已经类似于数值与数组下标逆向,需要消耗大量的空间);

          a.生成 n 个桶,并设定每个桶的取值范围(可以去最大值后,向 n 倍数取上整,便于 hash 计算),时间复杂度 O(N),空间复杂度O(N),

          b.遍历整个数组,将元素放入所属桶,并根据插入排序保持桶的有序,时间复杂度 ∑n-1i=0(啊~!不会用这个数学符号编辑啊)O(ni2),其中 ni 表示每次插入排序时当前桶的数量。

          综上所述,时间复杂度的总时间为 O(N) + ... 上面的数学公式,以后学会怎么编辑再来修改。当数据服从均匀分布时,每次的插入排序期望值为 n*O(2-1/N),验证较为复杂,有兴趣的同学可以参考算法导论.114页。

          可以得出时间复杂度为 O(N)

 

 

 

 

 

 

 

 

 

 

 

 

 

 


推荐阅读
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 使用Numpy实现无外部库依赖的双线性插值图像缩放
    本文介绍如何仅使用Numpy库,通过双线性插值方法实现图像的高效缩放,避免了对OpenCV等图像处理库的依赖。文中详细解释了算法原理,并提供了完整的代码示例。 ... [详细]
  • 非公版RTX 3080显卡的革新与亮点
    本文深入探讨了图形显卡的进化历程,重点介绍了非公版RTX 3080显卡的技术特点和创新设计。 ... [详细]
  • 深入理解OAuth认证机制
    本文介绍了OAuth认证协议的核心概念及其工作原理。OAuth是一种开放标准,旨在为第三方应用提供安全的用户资源访问授权,同时确保用户的账户信息(如用户名和密码)不会暴露给第三方。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • C++实现经典排序算法
    本文详细介绍了七种经典的排序算法及其性能分析。每种算法的平均、最坏和最好情况的时间复杂度、辅助空间需求以及稳定性都被列出,帮助读者全面了解这些排序方法的特点。 ... [详细]
  • 深入理解C++中的KMP算法:高效字符串匹配的利器
    本文详细介绍C++中实现KMP算法的方法,探讨其在字符串匹配问题上的优势。通过对比暴力匹配(BF)算法,展示KMP算法如何利用前缀表优化匹配过程,显著提升效率。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 机器学习中的相似度度量与模型优化
    本文探讨了机器学习中常见的相似度度量方法,包括余弦相似度、欧氏距离和马氏距离,并详细介绍了如何通过选择合适的模型复杂度和正则化来提高模型的泛化能力。此外,文章还涵盖了模型评估的各种方法和指标,以及不同分类器的工作原理和应用场景。 ... [详细]
  • 本文探讨了如何在编程中正确处理包含空数组的 JSON 对象,提供了详细的代码示例和解决方案。 ... [详细]
  • Yii 实现阿里云短信发送 ... [详细]
  • 从 .NET 转 Java 的自学之路:IO 流基础篇
    本文详细介绍了 Java 中的 IO 流,包括字节流和字符流的基本概念及其操作方式。探讨了如何处理不同类型的文件数据,并结合编码机制确保字符数据的正确读写。同时,文中还涵盖了装饰设计模式的应用,以及多种常见的 IO 操作实例。 ... [详细]
  • 本文探讨了 C++ 中普通数组和标准库类型 vector 的初始化方法。普通数组具有固定长度,而 vector 是一种可扩展的容器,允许动态调整大小。文章详细介绍了不同初始化方式及其应用场景,并提供了代码示例以加深理解。 ... [详细]
  • 本文详细介绍了如何在Ubuntu系统中下载适用于Intel处理器的64位版本,涵盖了不同Linux发行版对64位架构的不同命名方式,并提供了具体的下载链接和步骤。 ... [详细]
author-avatar
in冷霜天
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有