谈谈算法的时间复杂度
问题一:我们如何判断一个算法的优劣?
答:在不考虑额外空间开销的情况小,对于同一个问题,直观而言,解决这个问题的算法需要的时间越少,我们就可以认为这个算法的效率越高。
就比如:如果我们需要在有序数组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)
参考:算法第四版。
谈谈算法的时间复杂度相关推荐
- a*算法的时间复杂度_算法基础——时间复杂度amp;空间复杂度
关注.星标公众号,学点计算机知识. 整理:persistenceBin 今天来跟大家继续分享一下数据结构的基础知识--算法效率的度量:时间复杂度和空间复杂度.首先来跟大家分享一下在电影<复仇者联 ...
- a*算法的时间复杂度_从经典算法题看时间复杂度
本文首发公众号:架构精进,排版比较清晰. 经常有同学在 LeetCode 的题解中问解法的复杂度是多少.作为一个懒人,我一直在「逃避」这个问题,毕竟这东西听起来就这么「复杂」. 但本着对题解认真负责 ...
- 【转】算法中时间复杂度概括——o(1)、o(n)、o(logn)、o(nlogn)
2019独角兽企业重金招聘Python工程师标准>>> 在描述算法复杂度时,经常用到o(1), o(n), o(logn), o(nlogn)来表示对应算法的时间复杂度.这里进行归纳 ...
- 常用的排序算法的时间复杂度和空间复杂度
常用的排序算法的时间复杂度和空间复杂度 1.时间复杂度 (1)时间频度 一个算法执行所耗费的时间,从理论上是不能算出 ...
- 【计算理论】计算复杂性 ( 小 O 记号 | 严格渐进上界 | 分析算法的时间复杂度 )
文章目录 一.小 O 记号 ( 严格渐进上界 ) 二.分析算法的时间复杂度 一.小 O 记号 ( 严格渐进上界 ) 如果 g(n)\rm g(n)g(n) 是 f(n)\rm f(n)f(n) 渐进上 ...
- 关于算法的时间复杂度和空间复杂度的总结
一.算法的概念 算法(Algorithm)是将一组输入转化为一组输出的一系列计算步骤,其中每个步骤必须能在有限时间内完成.算法是用来解决一类计算问题的,注意是一类问题,而不是一个特定的问题. 二. ...
- 简单分析算法的时间复杂度
目录 一.什么是算法的时间复杂度 二.如何分析一个算法的时间复杂度 1.有确定次数的算法 2.次数不确定的算法 一.什么是算法的时间复杂度 时间复杂度是一个函数 ,定性描述一个算法(程 ...
- 【算法的时间复杂度和空间复杂度】-算法02
算法的时间复杂度和空间复杂度 一个算法的好坏我们主要从"时间"和"空间" 两个维度来衡量 时间维度:是指执行当前算法所消耗的时间,我们通常用 "时间复 ...
- 《大话数据结构》第2章 算法基础 2.9 算法的时间复杂度
2.9 算法的时间复杂度 2.9.1 算法时间复杂度定义 在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级.算法的时间复杂度,也就 ...
最新文章
- Java设计模式 创建模式-单态模式(Singleton)
- (转)Paper list of Meta Learning/ Learning to Learn/ One Shot Learning/ Lifelong Learning
- 物联网协议之CoAP协议开发学习笔记之术语解释
- 前端学习(1676):前端系列实战课程之贪吃蛇游戏设计
- 计算机桌面上的声音图标没了怎么办,Win7电脑右下角声音图标不见了怎么办?...
- 如何保护.net中的dll文件(防破解、反编译)
- (转载)Python函数参数传递机制(超级详细)
- Web调试工具:火狐Firefox插件Firebug介绍
- mysql 设置域名_mysql 设置域名
- MongoDB副本集配置系列二:配置MongoDB副本集
- SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder“.
- 应对Flash中国版流氓后台偷窥的解决方法
- Python自动批量删除微博
- 【浏览器被劫持解决方案】https://www.hao123.com/?tn=9762xxxx2644_hao_pg
- mini2440 sd卡加载过程详解
- 电话聊天狂人(25 分)
- android 选择答题功能,Android实现选择题答题(包括单选、多选和答题卡)
- aspose-words,pdf
- 【learning】微信跳一跳辅助c++详解 轻松上万 【下】
- 年后跳槽:哪些迹象告诉我们,公司可能不行了?