算法的时间复杂度计算
算法的时间复杂度和空间复杂度-总结分析

算法的时间复杂度和空间复杂度-总结通常,对于一个给定的算法,我们要做两项分析。
第一是从数学上证明算法的正确性,这一步主要用到形式化证明的方法及相关推理模式,如循环不变式、数学归纳法等。
而在证明算法是正确的基础上,第二部就是分析算法的时间复杂度。
算法的时间复杂度反映了程序执行时间随输入规模增长而增长的量级,在很大程度上能很好反映出算法的优劣与否。
因此,作为程序员,掌握基本的算法时间复杂度分析方法是很有必要的。
算法执行时间需通过依据该算法编制的程序在计算机上运行时所消耗的时间来度量。
而度量一个程序的执行时间通常有两种方法。
一、事后统计的方法这种方法可行,但不是一个好的方法。
该方法有两个缺陷:一是要想对设计的算法的运行性能进行评测,必须先依据算法编制相应的程序并实际运行;二是所得时间的统计量依赖于计算机的硬件、软件等环境因素,有时容易掩盖算法本身的优势。
二、事前分析估算的方法因事后统计方法更多的依赖于计算机的硬件、软件等环境因素,有时容易掩盖算法本身的优劣。
因此人们常常采用事前分析估算的方法。
在编写程序前,依据统计方法对算法进行估算。
一个用高级语言编写的程序在计算机上运行时所消耗的时间取决于下列因素:(1). 算法采用的策略、方法;(2). 编译产生的代码质量;(3). 问题的输入规模;(4). 机器执行指令的速度。
一个算法是由控制结构(顺序、分支和循环3种)和原操作(指固有数据类型的操作)构成的,则算法时间取决于两者的综合效果。
为了便于比较同一个问题的不同算法,通常的做法是,从算法中选取一种对于所研究的问题(或算法类型)来说是基本操作的原操作,以该基本操作的重复执行的次数作为算法的时间量度。
1、时间复杂度(1)时间频度一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。
但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了。
并且一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。
算法分类,时间复杂度,空间复杂度,优化算法

算法分类,时间复杂度,空间复杂度,优化算法算法 今天给⼤家带来⼀篇关于算法排序的分类,算法的时间复杂度,空间复杂度,还有怎么去优化算法的⽂章,喜欢的话,可以关注,有什么问题,可以评论区提问,可以与我私信,有什么好的意见,欢迎提出.前⾔: 算法的复杂度分为时间复杂度与空间复杂度,时间复杂度指执⾏算法需要需要的计算⼯作量,空间复杂度值执⾏算法需要的内存量,可能在运⾏⼀些⼩数据的时候,⼤家体会不到算法的时间与空间带来的体验. 优化算法就是将算法的时间优化到最快,将空间优化到最⼩,假如你写的mod能够将百度游览器的搜索时间提升0.5秒,那都是特别厉害的成绩.本章内容: 1,算法有哪些 2,时间复杂度,空间复杂度 3,优化算法 4,算法实例⼀,算法有哪些 常见的算法有冒泡排序,快排,归并,希尔,插⼊,⼆分法,选择排序,⼴度优先搜索,贪婪算法,这些都是新⼿⼊门必须要了解的,你可以不会,但是你必须要知道他是怎么做到的,原理是什么,今天就给⼤家讲⼀讲我们常⽤的冒泡排序,选择排序,这两个排序算法,1,冒泡排序(Bubble Sort), 为什么叫他冒泡排序呢? 因为他就像是从海底往海⾯升起的⽓泡⼀样,从⼩到⼤,将要排序的数从⼩到⼤排序,冒泡的原理: 他会⼀次⽐较两个数字,如果他们的顺序错误,就将其调换位置,如果排序正确的话,就⽐较下⼀个,然后重复的进⾏,直到⽐较完毕,这个算法的名字也是这样由来的,越⼤的数字,就会慢慢的'浮'到最顶端. 好了该上代码了,下⾯就是冒泡排序的代码,冒泡相对于其他的排序算法来说,⽐较的简单,⽐较好理解,运算起来也是⽐较迅速的,⽐较稳定,在⼯作中也会经常⽤到,推荐使⽤# 冒泡排序def bubble_sort(alist):n = len(alist)# 循环遍历,找到当前列表中最⼤的数值for i in range(n-1):# 遍历⽆序序列for j in range(n-1-i):# 判断当前节点是否⼤于后续节点,如果⼤于后续节点则对调if alist[j] > alist[j+1]:alist[j], alist[j+1] = alist[j+1], alist[j]if__name__ == '__main__':alist = [12,34,21,56,78,90,87,65,43,21]bubble_sort(alist)print(alist)# 最坏时间复杂度: O(n^2)# 最优时间复杂度: O(n)# # 算法稳定性:稳定2,选择排序(selection sort) 选择排序(selection sort)是⼀种简单直观的排序⽅法, 他的原理是在要排序的数列中找到最⼤或者最⼩的元素,放在列表的起始位置,然后从其他⾥找到第⼆⼤,然后第三⼤,依次排序,依次类,直到排完, 选择排序的优点是数据移动, 在排序中,每个元素交换时,⾄少有⼀个元素移动,因此N个元素进⾏排序,就会移动 1--N 次,在所有依靠移动元素来排序的算法中,选择排序是⽐较优秀的⼀种选择排序时间复杂度与稳定性:最优时间复杂度: O(n2)最坏时间复杂度:O(n2)算法稳定性 :不稳定(考虑每次升序选择最⼤的时候)# if alist[j] < alist[min_index]:# min_index = j## # 判断min_index索引是否相同,不相同,做数值交换# if i != min_index:# alist[i],alist[min_index] = alist[min_index],alist[i]### if __name__ == '__main__':# alist = [12,34,56,78,90,87,65,43,21]# # alist = [1,2,3,4,5,6,7,8,9]# select_sort(alist)# print(alist)# O(n^2)# 不稳定def select_sort(alist):"""选择排序"""n = len(alist)for i in range(n - 1):min_index = i # 最⼩值位置索引、下标for j in range(i+1, n):if alist[j] < alist[min_index]:min_index = j# 判断min_index ,如果和初始值不相同,作数值交换if min_index != i:alist[i], alist[min_index] = alist[min_index],alist[i]if__name__ == '__main__':alist = [8,10,15,30,25,90,66,2,999]select_sort(alist)print(alist)这是⼀些算法的时间复杂度与稳定性时间复杂度,空间复杂度 接下来就要来说说时间复杂度与空间复杂度: 时间复杂度就是假如你泡茶,从开始泡,到你喝完茶,⼀共⽤了多长时间,你中间要执⾏很多步骤,取茶叶,烧⽔,上厕所,接电话,这些都是要花时间的,在算法中,时间复杂度分为 O(1)最快 , O(nn)最慢,O(1) < O(logn) <O(n)<O(n2)<O(n3)<O(2n) <O(nn) ⼀般游览器的速度都在O(n),做我们这⼀⾏,要注意客户体验,如果你程序的运⾏特别慢,估计别⼈来⼀次,以后再也不会来了下⾯给⼤家找了张如何计算时间复杂度的图⽚: 空间复杂度(space complexity) ,执⾏时所需要占的储存空间,记做 s(n)=O(f(n)),其中n是为算法的⼤⼩, 空间复杂度绝对是效率的杀⼿,曾经看过⼀遍⽤插⼊算法的代码,来解释空间复杂度的,觉得特别厉害,我就⽐较low了,只能给⼤家简单的总结⼀下我遇到的空间复杂度了, ⼀般来说,算法的空间复杂度值得是辅助空间,⽐如:⼀组数字,时间复杂度O(n),⼆维数组a[n][m] :那么他的空间复杂度就是O(n*m) ,因为变量的内存是⾃动分配的,第⼀个的定义是循环⾥⾯的,所以是n*O(1) ,如果第⼆个循环在外边,那么就是1*O(1) ,这⾥也只是⼀个了解性的东西,如果你的⼯作中很少⽤到,那么没有必要深究,因为⽤的真的很少优化算法这边带来了代码,你们在复制下来了python上运⾏⼀下,看⼀下⽤的时间与不同, ⾃然就懂了,这是未优化的算法''已知有a,b,c三个数,都是0-1000之内的数,且: a+b+c=1000 ⽽且 a**2+b**2=c**2 ,求a,b,c⼀共有多少种组合'''# 在这⾥加⼀个时间模块,待会好计算出结果import time# 记录开头时间start_time=time.time()# 把a,b,c循环出来for a in range(1001):for b in range(1001):for c in range(100):# 判断他主公式第⼀次,并未优化if a+b+c==1000 and a**2 + b**2 == c**2 :# 打印print("a=" ,a)print("b=" ,b)print("c=" ,c)else:passstop_time = time.time()print('⼀共耗时: %f'%(stop_time-start_time))# ⼀共耗时 156.875001秒这是第⼀次优化import time# 记录开头时间start_time=time.time()# 把a,b,c循环出来for a in range(1001):# 这⾥改成1001-a之后,他就不⽤再循环b了for b in range(1001-a):for c in range(100):# 判断他主公式第⼆次,优化了b,if a+b+c==1000 and a**2 + b**2 == c**2 :print("a=" ,a)print("b=" ,b)print("c=" ,c)else:passstop_time = time.time()print('⼀共耗时: %f'%(stop_time-start_time))# ⼀共耗时 50.557070秒最后⼀次优化import time# 记录开头时间start_time=time.time()# 把a,b,c循环出来for a in range(1001):for b in range(1001-a):c=1000 - a - b# 判断他主公式第三次,优化了b和cif a+b+c==1000 and a**2 + b**2 == c**2 :print("a=" ,a)print("b=" ,b)print("c=" ,c)else:passstop_time = time.time()print('⼀共耗时: %f'%(stop_time-start_time))# ⼀共耗时 2.551449秒从156秒优化到l2秒, 基本运算总数 * 基本运算耗时 = 运算时间这之间的耗时和你的机器有着很⼤的关系今天是12⽉30⽇,明天就要跨年了,祝⼤家2019年事业有成,⼯资直线上升,早⽇脱单,。
算法的时间复杂度和空间复杂度

相关知识介绍(所有定义只为帮助读者理解相关概念,并非严格定义):1、稳定排序和非稳定排序简单地说就是所有相等的数经过某种排序方法后,仍能保持它们在排序之前的相对次序,我们就说这种排序方法是稳定的。
反之,就是非稳定的。
比如:一组数排序前是a1,a2,a3,a4,a5,其中a2=a4,经过某种排序后为a1,a2,a4,a3,a5,则我们说这种排序是稳定的,因为a2排序前在a4的前面,排序后它还是在a4的前面。
假如变成a1,a4, a2,a3,a5就不是稳定的了。
2、内排序和外排序在排序过程中,所有需要排序的数都在内存,并在内存中调整它们的存储顺序,称为内排序;在排序过程中,只有部分数被调入内存,并借助内存调整数在外存中的存放顺序排序方法称为外排序。
3、算法的时间复杂度和空间复杂度所谓算法的时间复杂度,是指执行算法所需要的计算工作量。
一个算法的空间复杂度,一般是指执行这个算法所需要的内存空间。
功能:选择排序输入:数组名称(也就是数组首地址)、数组中元素个数算法思想简单描述:在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。
选择排序是不稳定的。
算法复杂度O(n2)--[n的平方void select_sort(int *x, int n){int i, j, min, t;for (i=0; i<n-1; i++) /*要选择的次数:0~n-2共n-1次*/{min = i; /*假设当前下标为i的数最小,比较后再调整*/for (j=i+1; j<n; j++)/*循环找出最小的数的下标是哪个*/{if (*(x+j) < *(x+min)){min = j; /*如果后面的数比前面的小,则记下它的下标*/}}if (min != i) /*如果min在循环中改变了,就需要交换数据*/{t = *(x+i);*(x+i) = *(x+min);*(x+min) = t;}}/*功能:直接插入排序输入:数组名称(也就是数组首地址)、数组中元素个数算法思想简单描述:在要排序的一组数中,假设前面(n-1) [n>=2] 个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。
matlab 时间空间复杂度计算

matlab 时间空间复杂度计算在计算机科学中,时间复杂度和空间复杂度是评估算法性能的两个重要指标。
而在MATLAB中,对于算法的时间复杂度和空间复杂度的计算与其他编程语言类似。
本文将从理论和实际应用的角度,详细介绍MATLAB中时间复杂度和空间复杂度的计算方法,并探讨如何优化算法以提高性能。
时间复杂度是衡量算法执行时间随输入规模增长而增长的程度,通常用大O符号表示。
它描述了算法执行所需的基本操作次数,并提供了一种粗略的估计。
在MATLAB中,我们可以使用复杂度符号库来计算时间复杂度。
常见的时间复杂度包括:-常数时间复杂度O(1):算法的执行时间不受输入规模的影响,例如直接访问数组元素。
-线性时间复杂度O(n):算法的执行时间与输入规模n成正比,例如遍历数组或链表。
-对数时间复杂度O(log n):算法的执行时间随输入规模n的对数增加,例如二分查找。
-平方时间复杂度O(n^2):算法的执行时间与输入规模n的平方成正比,例如嵌套循环。
在MATLAB中,可以通过分析循环、递归和函数的调用来判断算法的时间复杂度。
具体方法如下:1.计算循环次数:分析算法中的循环结构,找出循环变量的变化规律并计算循环次数。
通常情况下,循环结构的复杂度与循环次数成正比。
2.分析递归调用:递归算法的时间复杂度可以通过递归树来计算。
根据递推关系式和递归调用的次数,可以得到递归算法的复杂度。
3.考虑函数调用开销:函数调用也会耗费一定的时间,特别是输入和输出参数的传递。
因此,在计算算法复杂度时,需要考虑函数调用的开销。
空间复杂度是衡量算法在执行过程中所需的额外内存空间的大小,通常也用大O符号表示。
它描述了算法所需的内存空间随输入规模增长而增加的程度。
常见的空间复杂度包括:-常数空间复杂度O(1):算法所需的额外内存空间是固定的,与输入规模无关,例如只使用有限个额外变量。
-线性空间复杂度O(n):算法所需的额外内存空间与输入规模n成正比,例如需要创建一个与输入规模相同大小的数组来存储数据。
时间复杂度详解

时间复杂度详解时间复杂度详解什么是时间复杂度•时间复杂度是一种衡量算法执行效率的方式。
•它表示算法的运行时间与输入大小的关系,为我们提供了衡量算法性能的指标。
时间复杂度的表示•时间复杂度使用大O符号(O)来表示。
•O(n)表示算法的时间复杂度与输入规模n成正比。
常见的时间复杂度•O(1):常数时间复杂度,无论输入规模的大小,算法的执行时间都保持不变。
•O(log n):对数时间复杂度,随着输入规模的增加,算法的执行时间逐渐增长,但增长速度很慢。
•O(n):线性时间复杂度,算法的执行时间与输入规模n成比例增长。
•O(n log n):线性对数时间复杂度,随着输入规模的增加,算法的执行时间逐渐增长,但增长速度比O(n)慢。
•O(n^2):平方时间复杂度,算法的执行时间与输入规模n的平方成比例增长。
•O(2^n):指数时间复杂度,算法的执行时间随着输入规模n的增加而急剧增长。
•O(n!):阶乘时间复杂度,算法的执行时间随着输入规模n的增加而急剧增长。
如何计算时间复杂度•首先,确定算法的基本操作。
•其次,根据算法的基本操作,分析每个操作的时间复杂度。
•最后,根据每个操作的时间复杂度,确定整个算法的时间复杂度。
如何选择合适的算法•在设计算法时,我们应该选择时间复杂度低的算法。
•当输入规模较小时,可以选用时间复杂度较高但简单易懂的算法。
•当输入规模较大时,应该尽量选择时间复杂度较低的算法。
总结•时间复杂度是一种衡量算法执行效率的方式,它表示算法的运行时间与输入规模的关系。
•常见的时间复杂度包括常数时间复杂度、对数时间复杂度、线性时间复杂度等。
•计算时间复杂度的步骤包括确定算法的基本操作、分析每个操作的时间复杂度以及确定整体的时间复杂度。
•在选择算法时,应该根据输入规模选择合适的时间复杂度。
参考资料:[腾讯课堂-计算机科学与技术](。
算法时间复杂度计算公式

算法时间复杂度计算公式算法(Algorithm)是指⽤来操作数据、解决程序问题的⼀组⽅法。
对于同⼀个问题,使⽤不同的算法,也许最终得到的结果是⼀样的,但在过程中消耗的资源和时间却会有很⼤的区别。
那么我们应该如何去衡量不同算法之间的优劣呢?主要还是从算法所占⽤的「时间」和「空间」两个维度去考量。
时间维度:是指执⾏当前算法所消耗的时间,我们通常⽤「时间复杂度」来描述。
空间维度:是指执⾏当前算法需要占⽤多少内存空间,我们通常⽤「空间复杂度」来描述。
因此,评价⼀个算法的效率主要是看它的时间复杂度和空间复杂度情况。
然⽽,有的时候时间和空间却⼜是「鱼和熊掌」,不可兼得的,那么我们就需要从中去取⼀个平衡点。
下⾯我来分别介绍⼀下「时间复杂度」和「空间复杂度」的计算⽅式。
⼀、时间复杂度我们想要知道⼀个算法的「时间复杂度」,很多⼈⾸先想到的的⽅法就是把这个算法程序运⾏⼀遍,那么它所消耗的时间就⾃然⽽然知道了。
这种⽅式可以吗?当然可以,不过它也有很多弊端。
这种⽅式⾮常容易受运⾏环境的影响,在性能⾼的机器上跑出来的结果与在性能低的机器上跑的结果相差会很⼤。
⽽且对测试时使⽤的数据规模也有很⼤关系。
再者,并我们在写算法的时候,还没有办法完整的去运⾏呢。
因此,另⼀种更为通⽤的⽅法就出来了:「⼤O符号表⽰法」,即 T(n) = O(f(n))我们先来看个例⼦:for(i=1; i<=n; ++i){j = i;j++;}通过「⼤O符号表⽰法」,这段代码的时间复杂度为:O(n) ,为什么呢?在⼤O符号表⽰法中,时间复杂度的公式是: T(n) = O( f(n) ),其中f(n) 表⽰每⾏代码执⾏次数之和,⽽ O 表⽰正⽐例关系,这个公式的全称是:算法的渐进时间复杂度。
我们继续看上⾯的例⼦,假设每⾏代码的执⾏时间都是⼀样的,我们⽤ 1颗粒时间来表⽰,那么这个例⼦的第⼀⾏耗时是1个颗粒时间,第三⾏的执⾏时间是 n个颗粒时间,第四⾏的执⾏时间也是 n个颗粒时间(第⼆⾏和第五⾏是符号,暂时忽略),那么总时间就是 1颗粒时间 + n颗粒时间 + n颗粒时间,即 (1+2n)个颗粒时间,即: T(n) = (1+2n)*颗粒时间,从这个结果可以看出,这个算法的耗时是随着n的变化⽽变化,因此,我们可以简化的将这个算法的时间复杂度表⽰为:T(n) = O(n)为什么可以这么去简化呢,因为⼤O符号表⽰法并不是⽤于来真实代表算法的执⾏时间的,它是⽤来表⽰代码执⾏时间的增长变化趋势的。
最大公约数的三种算法复杂度分析时间计算

最大公约数的三种算法复杂度分析时间计算1.辗转相除法(欧几里得算法)辗转相除法是一种基于递归的算法,它通过不断地用两个数中较大的数除以较小的数,直到两个数相等为止。
这时,较小的数就是最大公约数。
例如,求解49和28的最大公约数:-49÷28=1 (21)-28÷21=1 (7)-21÷7=3 0所以最大公约数为7辗转相除法的时间复杂度分析如下:设两个数中较大的数为a,较小的数为b,a mod b 的结果为r。
- 最好情况:当b能够整除a时,时间复杂度为O(loga),因为每次递归时a和b的值都会减少至原来的一半。
-最坏情况:当a和b互质时,时间复杂度为O(a/b)。
例如,当a=2n 时,每次递归的b的值都会减少至1- 平均情况:时间复杂度是O(logab)的。
2.更相减损术更相减损术是一种基于减法的算法,它通过不断地用两个数中较大的数减去较小的数,直到两个数相等为止。
这时,较小的数就是最大公约数。
例如,求解49和28的最大公约数:-28-21=7-21-7=14-14-7=7所以最大公约数为7更相减损术的时间复杂度分析如下:设两个数中较大的数为a,较小的数为b。
- 最好情况:当a和b的差值为1时,时间复杂度为O(logb),因为每次减法操作后的差值都会减少一半。
-最坏情况:当a和b互质时,时间复杂度为O(a-b)。
例如,当a=2n 时,每次减法操作的差值都会减少至1-平均情况:时间复杂度为O(a-b)的。
3. Stein算法(二进制法)Stein算法是一种基于位运算的算法,它通过在两个数中同时除去2的因子,直到两个数都变为奇数。
然后,继续用较小的数减去较大的数,直到两个数相等为止。
这时,较小的数就是最大公约数的2的因子。
例如,求解49和28的最大公约数:-49÷2=24-28÷2=14-24÷2=12现在两个数都是奇数,继续减法操作:-7-12=-5-12-7=5所以最大公约数为5Stein算法的时间复杂度分析如下:设两个数中较大的数为a,较小的数为b。
算法的时间复杂度和空间复杂度简单理解

算法的时间复杂度和空间复杂度简单理解时间复杂度是指执⾏算法所需要的计算⼯作量;⽽空间复杂度是指执⾏这个算法所需要的内存空间。
(算法的复杂性体现在运⾏该算法时的计算机所需资源的多少上,计算机资源最重要的是时间和空间(即寄存器)资源,因此复杂度分为时间和空间复杂度在描述算法复杂度时,经常⽤到o(1), o(n), o(logn), o(nlogn)来表⽰对应算法的时间复杂度。
这⾥进⾏归纳⼀下它们代表的含义:这是算法的时空复杂度的表⽰。
不仅仅⽤于表⽰时间复杂度,也⽤于表⽰空间复杂度。
⼀个算法的优劣主要从算法的所需时间和所占⽤的空间两个⽅⾯衡量。
⼀般空间利⽤率⼩的,所需时间相对较长。
所以性能优化策略⾥⾯经常听到空间换时间,时间换空间这样说法 O后⾯的括号中有⼀个函数,指明某个算法的耗时/耗空间与数据增长量之间的关系。
其中的n代表输⼊数据的量。
1. ⽐如时间复杂度为O(n),就代表数据量增⼤⼏倍,耗时也增⼤⼏倍。
⽐如常见的遍历算法。
int x=1; while (x <n){ x++; } list.contains()⽅法,系统会对list中的每个元素e调⽤o.equals(e),因此⽤时间复杂度表⽰是O(n) 该算法执⾏次数是如果n=10, 执⾏次数就是10,n是个变量,⽤时间复杂度表⽰是O(n)。
2. 再⽐如时间复杂度O(n^2),就代表数据量增⼤n倍时,耗时增⼤n的平⽅倍,这是⽐线性更⾼的时间复杂度。
⽐如冒泡排序,就是典型的O(n^2)的算法,对n个数排序,需要扫描n×n次。
for (i = 0; i < n; i++){ for (j = 0; j < n; j++){ //... } } 如果两层循环,该算法for循环,最外层循环每执⾏⼀次,内层循环都要执⾏n次,执⾏次数是根据n所决定的,最⼤时间复杂度是O(n^2),如果内层循环在某种场景⼀次就跳出,其实也可以退化成o(n), 通常我们计算时间复杂度都是计算最多情况.由此类推,如果是三层循环,最⼤时间复杂度就是 O(n^3).⽐如冒泡、选择等等 3. O(1)就是最低的时空复杂度了,也就是耗时/耗空间与输⼊数据⼤⼩⽆关,⽆论输⼊数据增⼤多少倍,耗时/耗空间都不变。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
for(i=1;i<=n;i++)
for(j=1;j<=i;j++)
for(k=1;k<=j;k++)
x++;
它的时间复杂度是多少?
自己计算了一下,数学公式忘得差不多了,郁闷;
(1)时间复杂性是什么?
时间复杂性就是原子操作数,最里面的循环每次执行j次,中间循环每次执行
a[i]=1+2+3+...+i=i*(i+1)/2次,所以总的时间复杂性=a[1]+...+a[i]+..+a[n];
a[1]+...+a[i]+..+a[n]
=1+(1+2)+(1+2+3)+...+(1+2+3+...+n)
=1*n+2*(n-1)+3*(n-2)+...+n*(n-(n-1))
=n+2n+3n+...+n*n-(2*1+3*2+4*3+...+n*(n-1))
=n(1+2+...+n)-(2*(2-1)+3*(3-1)+4*(4-1)+...+n*(n-1))
=n(n(n+1))/2-[(2*2+3*3+...+n*n)-(2+3+4+...+n)]
=n(n(n+1))/2-[(1*1+2*2+3*3+...+n*n)-(1+2+3+4+...+n)]
=n(n(n+1))/2-n(n+1)(2n+1)/6+n(n+1)/2
所以最后结果是O(n^3)。
【转】时间复杂度的计算
算法复杂度是在《数据结构》这门课程的第一章里出现的,因为它稍微涉及到一些数学问题,所以很多同学感觉很难,加上这个概念也不是那么具体,更让许多同学复习起来无从下手,
下面我们就这个问题给各位考生进行分析。
首先了解一下几个概念。
一个是时间复杂度,一个是渐近时间复杂度。
前者是某个算法的时间耗费,它是该算法所求解问题规模n的函数,而后者是指当问题规模趋向无穷大时,该算法时间复杂度的数量级。
当我们评价一个算法的时间性能时,主要标准就是算法的渐近时间复杂度,因此,在算法分析时,往往对两者不予区分,经常是将渐近时间复杂度T(n)=O(f(n))简称为时间复杂度,其中的f(n)一般是算法中频度最大的语句频度。
此外,算法中语句的频度不仅与问题规模有关,还与输入实例中各元素的取值相关。
但是我们总是考虑在最坏的情况下的时间复杂度。
以保证算法的运行时间不会比它更长。
常见的时间复杂度,按数量级递增排列依次为:常数阶O(1)、对数阶O(log2n)、线性阶O(n)、线性对数阶O(nlog2n)、平方阶O(n^2)、立方阶O(n^3)、k次方阶O(n^k)、指数阶O(2^n)。
下面我们通过例子加以说明,让大家碰到问题时知道如何去解决。
1、设三个函数f,g,h分别为f(n)=100n^3+n^2+1000 , g(n)=25n^3+5000n^2 , h(n)=n^1.5+5000nlgn
请判断下列关系是否成立:
(1)f(n)=O(g(n))
(2)g(n)=O(f(n))
(3)h(n)=O(n^1.5)
(4)h(n)=O(nlgn)
这里我们复习一下渐近时间复杂度的表示法T(n)=O(f(n)),这里的"O"是数学符号,它的严格定义是"若T(n)和f(n)是定义在正整数集合上的两个函数,则T(n)=O(f(n))表示存在正的常数C和n0 ,使得当n≥n0时都满足0≤T(n)≤C?f(n)。
"用容易理解的话说就是这两个函数当整型自变量n趋向于无穷大时,两者的比值是一个不等于0的常数。
这么一来,就好计算了吧。
◆(1)成立。
题中由于两个函数的最高次项都是n^3,因此当n→∞时,两个函数的比值是一个常数,所以这个关系式是成立的。
◆(2)成立。
与上同理。
◆(3)成立。
与上同理。
◆(4)不成立。
由于当n→∞时n^1.5比nlgn递增的快,所以h(n)与nlgn的比值不是常数,
故不成立。
2、设n为正整数,利用大"O"记号,将下列程序段的执行时间表示为n的函数。
(1) i=1; k=0
while(i<n)
{ k=k+10*i;i++;
}
解答:T(n)=n-1,T(n)=O(n),这个函数是按线性阶递增的。
(2) x=n; // n>1
while (x>=(y+1)*(y+1))
y++;
解答:T(n)=n1/2 ,T(n)=O(n1/2),最坏的情况是y=0,那么循环的次数是n1/2次,这是一个按平方根阶递增的函数。
(3) x=91; y=100;
while(y>0)
if(x>100)
{x=x-10;y--;}
else x++;
解答:T(n)=O(1),这个程序看起来有点吓人,总共循环运行了1000次,但是我们看到n 没有? 没。
这段程序的运行是和n无关的,就算它再循环一万年,我们也不管他,只是一个常数阶的函数。
-----------------------------------------------------------
1.1 大O表示法
上学的时候就学习了大O表示法表示一个算法的效率,也大概明白怎么回事,知道如果没有循环的一段程序的复杂度是常数,一层循环的复杂度是O(n),两层循环的复杂度是O(n^2)? (我用^2表示平方,同理^3表示立方)。
但是一直对于严格的定义和用法稀里糊涂。
1.1.1 定义
设一个程序的时间复杂度用一个函数T(n) 来表示,对于一个查找算法,如下:
int seqsearch( int a[], const int n, const int x)
{
int i = 0;
for (; a[i] != x && i < n ; i++ );
if ( i == n) return -1;
else return i;
}这个程序是将输入的数值顺序地与数组中地元素逐个比较,找出与之相等地元素。
在第一个元素就找到需要比较一次,在第二个元素找到需要比较2次,……,在第n个元素找到需要比较n次。
对于有n个元素的数组,如果每个元素被找到的概率相等,那么查找成功的平均比较次数为:
f(n) = 1/n (n + (n-1) + (n-2) + ... + 1) = (n+1)/2 = O(n)
这就是传说中的大O函数的原始定义。
1.1.2 用大O来表述
要全面分析一个算法,需要考虑算法在最坏和最好的情况下的时间代价,和在平均情况下的时间代价。
对于最坏情况,采用大O表示法的一般提法(注意,这里用的是“一般提法”)是:当且仅当存在正整数c和n0,使得T(n) <= c*f(n)对于所有的n >= n0 都成立。
则称该算法的渐进时间复杂度为T(n) = O(f(n))。
这个应该是高等数学里面的第一章极限里面的知识。
这里f(n) = (n+1)/2, 那么c * f(n)也就是一个一次函数。
对于对数级,我们用大O记法记为O(log2N)就可以了。
1.1.3 加法规则
T(n,m) = T1(n) + T2(n) = O ( max (f(n), g(m) )
1.1.4 乘法规则
T(n,m) = T1(n) * T2(m) = O (f(n) * g(m))
1.1.5 一个特例
在大O表示法里面有一个特例,如果T1(n) =O(c),c是一个与n无关的任意常数,T2(n) = O ( f(n) ) 则有
T(n) = T1(n) * T2(n) = O ( c*f(n) ) = O( f(n) ).
也就是说,在大O表示法中,任何非0正常数都属于同一数量级,记为O(1)。
1.1.6 一个经验规则
有如下复杂度关系
c < log2N < n < n * Log2N < n^2 < n^3 < 2^n < 3^n < n!
其中c是一个常量,如果一个算法的复杂度为c 、log2N 、n 、n*log2N ,那么这个算法时间效率比较高,如果是2^n , 3^n ,n!,那么稍微大一些的n就会令这个算法不能动了,居于中间的几个则差强人意。
本文来自CSDN博客,转载请标明出处:/liyan622/archive/2009/11/26/4876194.aspx。