0. 时间复杂度

接触到算法的小伙伴们都会知道时间复杂度(Time Complexity)的概念,这里先放出(渐进)时间复杂度的定义:

假设问题规模是\(n\),算法中基本操作重复执行的次数是\(n\)的某个函数,用\(T(n)\)表示,若有某个辅助函数\(f(n)\),使得

\[\lim_{n\rightarrow \infty}{T(n)/f(n)} = c
\]

其中\(c\)为不等于零的常数,则称\(f(n)\)是\(T(n)\)的同数量级函数。记作\(T(n)=O(f(n))\),称\(O(f(n))\) 为算法的渐进时间复杂度,简称时间复杂度。

常见的时间复杂度有(表格越靠后表示越不理想):

复杂度 名称
\(O(1)\) 常数阶
\(O(\log n)\) 对数阶
\(O(n)\) 线性阶
\(O(n\log n)\) 线性对数阶
\(O(n^2)\) 平方阶
\(O(n^3)\) 立方阶
\(O(n^k)\) \(k\)次方阶(\(k>3\)且\(k\in Z\))
\(O(2^n)\) 指数阶

例如,我们熟悉的插入排序(Insertion Sort)算法的时间复杂度是\(O(n^2)\),而合并排序(Merge Sort)算法的时间复杂度是\(O(n\log n)\)

那么这些复杂度之间的差距是怎么样的呢?有些小伙伴会疑问,自己写的算法虽然是高复杂度但是也用的好好的,为什么要纠结于这个概念呢?

我们不妨来探索一下今天的问题:\(O(n^2)\)和\(O(n\log n)\)差距有多大?

1. \(O(n^2)\)和\(O(n\log n)\)差距有多大?

我们知道,插入排序(Insertion Sort)算法的时间复杂度是\(O(n^2)\),而合并排序(Merge Sort)算法的时间复杂度是\(O(n\log n)\),即当排序\(n\)个对象时,插入排序算法需要用时大约\(c_1n^2\),而合并排序算法需要用时大约\(c_2n\log{n}\),其中\(c_1\)和\(c_2\)都是正常数且与\(n\)无关,且往往\(c_1<c_2\)。

稍微利用初等数学的知识,可以知道,对于任何\(n>=2\),比较约\(c_1n^2\)和\(c_2n\log{n}\)即比较\(c_1n\)和\(c_2\log{n}\)。由于我们已知

\[c_1<c_2
\]

以及

\[\log{n} < n
\]

想要比较这两个值的大小,直观的看法就是比较两个不等式谁的差别“更多”。可以证明,当无论\(c_1\)和\(c_2\)差别多么显著,总存在充分大的\(N\)使得当\(n>N\)时,\(c_1n>c_2\log{n}\)。

Introduction to Algorithms中,作者举了一个很有趣的例子:

假设针对同一排序问题,用一台很快的电脑A运行插入排序,用一台很慢的电脑B运行合并排序,问题规模\(n=10^7\):

两台电脑的差别如下,为了使A比B优势显著,作者假设电脑A性能比B强1000倍,并且B运行的代码更低效、且编译器更差(导致需要运行更多的指令):

电脑A 电脑B
每秒运行指令数 \(10^{10}\) \(10^7\)
需要运行的指令总数 \(2n^2\) \(50n\log n\)

这样,A完成任务需要:

\[\frac{2\cdot(10^7)^2}{10^{10}} = 20,000\quad seconds
\]

而B完成任务需要:

\[\frac{50\cdot 10^7\log 10^7}{10^{7}} \approx 1,163 \quad seconds
\]

可以看到,在这样的大规模的问题下,即便B计算机与A差距巨大,最终也只用了20分钟左右就完成排序,而A却需要5.5小时来完成。时间复杂度的差距可见一斑。

3. 总结

算法时间复杂度的量级差异,也许在小规模的问题下,表现差别不大。但是时间复杂度高的算法,对问题规模的变化更加敏感,因而当问题的规模变得很大的时候,靠拥有高阶时间复杂度的算法来求解并不可靠!

(更新)我从网络上找到了一个直观的各个阶的复杂度的对比,大家不妨参考一下:

# 喜欢就点个赞、关注支持一下吧!

参考:

Thomas H. Cormen, et al., Introduction to Algorithms Part I 1.2

http://www.bigocheatsheet.com

时间复杂度O(n^2)和O(nlog n)差距有多大?的更多相关文章

  1. 如何快速求解第一类斯特林数--nlog^2n + nlogn

    目录 参考资料 前言 暴力 nlog^2n的做法 nlogn的做法 代码 参考资料 百度百科 斯特林数 学习笔记-by zhouzhendong 前言 首先是因为这道题,才去研究了这个玩意:[2019 ...

  2. 【转】Java学习—什么是时间复杂度

    [原文]https://www.toutiao.com/i6593144782992704007/ 转载:程序员小灰 时间复杂度的意义 究竟什么是时间复杂度呢?让我们来想象一个场景: 某一天,小灰和大 ...

  3. 日常分享:关于时间复杂度和空间复杂度的一些优化心得分享(C#)

    前言 今天分享一下日常工作中遇到的性能问题和解决方案,比较零碎,后续会持续更新(运行环境为.net core 3.1) 本次分享的案例都是由实际生产而来,经过简化后作为举例 Part 1(作为简单数据 ...

  4. careercup-高等难度 18.6

    18.6 设计一个算法,给定10亿个数字,找出最小的100万个数字.假定计算机内存足以容纳全部10亿个数字. 解法: 方法1:排序 按升序排序所有的元素,然后取出前100万个数,时间复杂度为O(nlo ...

  5. [学习笔记] 多项式与快速傅里叶变换(FFT)基础

    引入 可能有不少OIer都知道FFT这个神奇的算法, 通过一系列玄学的变化就可以在 $O(nlog(n))$ 的总时间复杂度内计算出两个向量的卷积, 而代码量却非常小. 博主一年半前曾经因COGS的一 ...

  6. 最小k个数

    题目 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 思考 方法0: 直接排序然后返回前k个,最好的时间复杂度为 O(nlo ...

  7. 排序算法——(2)Python实现十大常用排序算法

    上期为大家讲解了排序算法常见的几个概念: 相关性:排序时是否需要比较元素 稳定性:相同元素排序后是否可能打乱 时间空间复杂度:随着元素增加时间和空间随之变化的函数 如果有遗忘的同学可以看排序算法——( ...

  8. 20172328 2018-2019《Java软件结构与数据结构》第五周学习总结

    20172328 2018-2019<Java软件结构与数据结构>第五周学习总结 概述 Generalization 本周学习了第九章:排序与查找,主要包括线性查找和二分查找算法和几种排序 ...

  9. 超详细的HashMap解析(jdk1.8)

    目录 一.预备知识 时间复杂度 基本数据结构 基本位运算 二.HashMap实现原理 结构 速度 三.源码分析 基本常量 基本成员变量 构造方法 put方法 remove 四.日常使用注意事项 五.总 ...

随机推荐

  1. 带你熟悉SQLServer2016中的System-Versioned Temporal Table 版本由系统控制的临时表

    什么是 System-Versioned Temporal Table? System-Versioned Temporal Table,暂且容我管它叫版本由系统控制的临时表,它是 SQL Serve ...

  2. centos 6.5下安装nmap工具及简单用法

    Nmap是一款针对大型网络的端口扫描工具,被广泛应用于黑客领域做漏洞探测以及安全扫描,其主要功能有主机发现(Host Discovery). 端口扫描(Port Scanning). 版本侦测(Ver ...

  3. Maven将依赖包、jar/war包及配置文件输出到指定目录

    使用Maven插件将依赖包 jar包 war包及配置文件输出到指定目录 写在前面 ​ 最近遇到一个朋友遇到一个项目需要将 maven 的依赖包和配置文件分开打包然后用脚本执行程序.这样的好处在于可以随 ...

  4. MySQL基本简单操作01

    MySQL基本简单操作 学会了安装Docker,那么就将它利用起来.(/滑稽脸) 之前想学习Mysql(Windows下配置真麻烦),学会了Docker就方便了,直接使用Docker创建一个Mysql ...

  5. Beta冲刺! Day3 - 砍柴

    Beta冲刺! Day3 - 砍柴 今日已完成 晨瑶:追查进度:确定推荐算法 昭锡:查看Note模块的处理逻辑.查找主页UI的解决方案 永盛:数据库的大量整合和新建,备份和还原:完成部分新的逻辑 立强 ...

  6. 【软件工程1916|W(福州大学)_助教博客】团队第四次作业(第7次)成绩公示

    1. 作业链接: https://edu.cnblogs.com/campus/fzu/SoftwareEngineering1916W/homework/2874 2. 评分准则: 本次作业评分分为 ...

  7. Django-组件拾遗

    Django的缓存机制 1.1 缓存介绍 在动态网站中,用户所有的请求,服务器都会去数据库中进行相应的增,删,查,改,渲染模板,执行业务逻辑,最后生成用户看到的页面. 当一个网站的用户访问量很大的时候 ...

  8. (12)Python异常

  9. Android事件处理第一节(View对Touch事件的处理)

    http://ipjmc.iteye.com/blog/1694146 在Android里Touch是很常用的事件,尤其实在自定义控件中,要实现一些动态的效果,往往要对Touch进行处理.Androi ...

  10. Perfect Pth Powers pku-1730(筛+合数分解)

    题意:x可以表示为bp, 求这个p的最大值,比如 25=52, 64=26,  然后输入x 输出 p 就是一个质因子分解.算法.(表示数据上卡了2个小时.) 合数质因子分解模板. ]; ]; ; ;n ...