问题一:我们如何判断一个算法的优劣?

答:在不考虑额外空间开销的情况小,对于同一个问题,直观而言,解决这个问题的算法需要的时间越少,我们就可以认为这个算法的效率越高。

就比如:如果我们需要在有序数组array中查找一个数key,返回这个key在数组中的下标,(我们假设这个key是在数组中一定存在的)。我们第一个反应是遍历整个数组。

for(int i=0;i<array.length;i++){if(array[i]==key)return i;
}

暴力求解,如此的简单,so easy.

但是如果我们这个数组里如果有一亿个数,那么在最坏情况下(比如这个数字在数组的末尾),我们需要遍历完整个数组才能找到这个数,那么我们需要的时间是非常大的,所以这个这个算法在数据量大的情况下显得不那么的友好。

所以我们通常不那么做,而是使用二分查找。(每次查找范围都缩小一半,知道找到这个数为止。)

public static int rank(int [] array,int key)
{//前提:数组有序
int low=0;
int height=array.length-1;
while(low<=height){int mid=low+(height-low)/2 //数组的中间索引。if(key<array[mid]) { height=mid-1;}if(key>array[mid]) {low=mid+1;}else return mid;}}

那么在最坏情况下,我们在这个数组中需要找打这个数,我们来计算一下查找的次数。第一次N/2,第二次N/2/2,第三次N/2/2/2

易得第m次N/2^m,所以找到这个数的最坏情况为(2^m=n,则m=log2(N))。

long(2N)的查找次数远远小于N。所以对于统一个问题,好的算法和坏的算法效率天壤之别。

我们既然知道,算法运行的快慢(时间的长短)是作为判断算法优劣的之一(今天只讲时间复杂度,还要考虑到空间复杂度),那么如何推广到一般性,即我们如何判断算法的执行时间呢?

问题二:如果我们需要知道一个算法执行的时间,我们应该怎么做。

解决一:直接用时间函数来统计,它根据计算机的不同,时间会不一样,但是我们如果想知道时间,每次都要实际操作才行,这样是不太现实的,有什么方法可以直观的得出一个算法的效率呢?直觉告诉我们它和问题的规模有关。

解决二,我们直接用数学模型来判断,我们根据执行语句执行的次数,来得出一个函数,这个函数就是问题的规模。这个问题的规模取决于最频繁的执行语句。显然算法运行时间是根据执行最频繁的语句的时间来决定的。

举个例子:

Int count=0;

For(int i=0;i<N;i++)

count++;

这个算法(姑且称之为算法吧),for循环这条语句执行的次数为N。问题的规模也为N。

所以这个算法执行的时间取决于N。

例子二:三数之和:

public static int sum(int [] a)
{统计数组中和为0的三元组的数量。
int count=0;
int N=a.length;
for(int i=0;i<N;i++)for(int j=i+1;j<N;j++)for(int k=j+1;k<N;k++)if(a[i]+a[j]+a[k]==0)count++;return count;}

在这个嵌套的三层循环中,我们可以看到,If语句是执行最频繁的那条语句,我们选取它作为这个算法执行的次数,可得它的执行的频率为N(N-1)(N-2)/6=N^3/6-N^2/2+N/3。。这条式子在这里就推导,有兴趣可以自行推导。

求近似

但是如果我们按照这样的分析,用语句执行的频率来作为算法的时间复杂度。那么当产生复杂数学表达式的时候,不利于我们分析这个算法的优劣。例如:

N(N-1)(N-2)/6=N^3/6-N^2/2+N/3。

这个表达式是不是看起来有点复杂,但是我们可以知道的是,一般在这种表达式中,随着N的增大,那么首项之后其他项的值都相对较小,(例如当N=1000时,-N^2/2+N/3≈499 667,而N^3/6≈166 666 667,).由此我们可以得出,我们可以去除非常复杂但是幂次较低的项,因为它们对于我们的结果影响较小。

当N不断增大的时候,N^3/6-N^2/2+N/3除以N3/6的值无限趋近于一。所以我们用N^3/6作为近似值

所以我们取近似值N^3/6。

再进一步我们忽略系数,而把所有的注意力集中在问题规模上,那么这个算法的时间复杂度为N^3.。所以我们以后取时间复杂度时,只取最高次幂并且忽略它的系数。

函数

近似

时间复杂度

N^3/6-N^2/2+N/3

N^3/6

N^3

N^2/2+N/3

N^2/2

N^2

lgN+1

lgN

lgN

3

3

1

常见的时间复杂度总结

描述

时间复杂度

典型代码

说明

常数级别

1

a+b=c

普通语句

对数级别

logN

二分查找

二分策略

线性级别

N

For(int i=0;i<N;i++)

{ }

循环

线性对数级别

NLogN

分治

归并排序

平方级别

N2

For(int i=0;i<N;i++){

For(int j=i;j<N;j++) { }

}

双层循环

立方级别

N3

三个for嵌套的for循环

三层循环

显然,对于算法,它的时间复杂度越低越好。如果一个算法的时间复杂度过高,那么对于我们来说是不可接受了,因为它实在是太慢了。

通常O(1)<O(logN)<O(N)<O(NLogN)<O(N^2)<O(N^3)<O(2^N)

参考:算法第四版。

谈谈算法的时间复杂度相关推荐

  1. a*算法的时间复杂度_算法基础——时间复杂度amp;空间复杂度

    关注.星标公众号,学点计算机知识. 整理:persistenceBin 今天来跟大家继续分享一下数据结构的基础知识--算法效率的度量:时间复杂度和空间复杂度.首先来跟大家分享一下在电影<复仇者联 ...

  2. a*算法的时间复杂度_从经典算法题看时间复杂度

    本文首发公众号:架构精进​,排版比较清晰. 经常有同学在 LeetCode 的题解中问解法的复杂度是多少.作为一个懒人,我一直在「逃避」这个问题,毕竟这东西听起来就这么「复杂」. 但本着对题解认真负责 ...

  3. 【转】算法中时间复杂度概括——o(1)、o(n)、o(logn)、o(nlogn)

    2019独角兽企业重金招聘Python工程师标准>>> 在描述算法复杂度时,经常用到o(1), o(n), o(logn), o(nlogn)来表示对应算法的时间复杂度.这里进行归纳 ...

  4. 常用的排序算法的时间复杂度和空间复杂度

    常用的排序算法的时间复杂度和空间复杂度                                           1.时间复杂度 (1)时间频度 一个算法执行所耗费的时间,从理论上是不能算出 ...

  5. 【计算理论】计算复杂性 ( 小 O 记号 | 严格渐进上界 | 分析算法的时间复杂度 )

    文章目录 一.小 O 记号 ( 严格渐进上界 ) 二.分析算法的时间复杂度 一.小 O 记号 ( 严格渐进上界 ) 如果 g(n)\rm g(n)g(n) 是 f(n)\rm f(n)f(n) 渐进上 ...

  6. 关于算法的时间复杂度和空间复杂度的总结

    一.算法的概念   算法(Algorithm)是将一组输入转化为一组输出的一系列计算步骤,其中每个步骤必须能在有限时间内完成.算法是用来解决一类计算问题的,注意是一类问题,而不是一个特定的问题. 二. ...

  7. 简单分析算法的时间复杂度

    目录 一.什么是算法的时间复杂度 二.如何分析一个算法的时间复杂度 1.有确定次数的算法 2.次数不确定的算法 一.什么是算法的时间复杂度         时间复杂度是一个函数 ,定性描述一个算法(程 ...

  8. 【算法的时间复杂度和空间复杂度】-算法02

    算法的时间复杂度和空间复杂度 一个算法的好坏我们主要从"时间"和"空间" 两个维度来衡量 时间维度:是指执行当前算法所消耗的时间,我们通常用 "时间复 ...

  9. 《大话数据结构》第2章 算法基础 2.9 算法的时间复杂度

    2.9 算法的时间复杂度 2.9.1 算法时间复杂度定义 在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级.算法的时间复杂度,也就 ...

最新文章

  1. Java设计模式 创建模式-单态模式(Singleton)
  2. (转)Paper list of Meta Learning/ Learning to Learn/ One Shot Learning/ Lifelong Learning
  3. 物联网协议之CoAP协议开发学习笔记之术语解释
  4. 前端学习(1676):前端系列实战课程之贪吃蛇游戏设计
  5. 计算机桌面上的声音图标没了怎么办,Win7电脑右下角声音图标不见了怎么办?...
  6. 如何保护.net中的dll文件(防破解、反编译)
  7. (转载)Python函数参数传递机制(超级详细)
  8. Web调试工具:火狐Firefox插件Firebug介绍
  9. mysql 设置域名_mysql 设置域名
  10. MongoDB副本集配置系列二:配置MongoDB副本集
  11. SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder“.
  12. 应对Flash中国版流氓后台偷窥的解决方法
  13. Python自动批量删除微博
  14. 【浏览器被劫持解决方案】https://www.hao123.com/?tn=9762xxxx2644_hao_pg
  15. mini2440 sd卡加载过程详解
  16. 电话聊天狂人(25 分)
  17. android 选择答题功能,Android实现选择题答题(包括单选、多选和答题卡)
  18. aspose-words,pdf
  19. 【learning】微信跳一跳辅助c++详解 轻松上万 【下】
  20. 年后跳槽:哪些迹象告诉我们,公司可能不行了?

热门文章

  1. 再见!杭州!再见!阿里巴巴
  2. js实现页面表格内容的复制粘贴填充,实现快速填写
  3. uni-app控制台显示项目编译成功,但模拟器没有反应
  4. 捕捉95%的习惯思维,让用户对你的产品上瘾
  5. 如何玩好“用户思维”
  6. Zabbix 邮件报警、钉钉报警、微信报警
  7. Windows家庭版如何打开本地组策略编辑器
  8. Batch Normalization在CNN中的原理,nb与lrb的区别
  9. windows 查看wifi密码命令
  10. python 鼠标 自动点击_鼠标隔段时间自动点击屏幕