算法性能分析
时间复杂度分析
递归算法的时间复杂度
例题一: 求x的n次方
用一道题目,同样使用递归算法, 有的写出了O(n)的代码,有的写出了O(longn)的代码
时间复杂度为:O(n)
最直观的写法, 一个for循环求出结果,代码如下:
def sample_1(x, n):
result = 1
for i in range(n):
result = result * x
return result
思考: 有没有效率更好的算法?
有的人一看到递归,就想到了O(logn), 其实并不是这样, 递归算法的时间复杂度本质上是要看-递归的次数 * 每次递归中的操作数
代码如下:
def sample_1_2(x, n):
if n == 0:
return 1
return sample_1_2(x, n)
使用迭代更改之后,时间复杂度为O(n), 每次n-1,递归了n次时间复杂度为O(n), 每次进去了一个乘法的操作,复杂度为O(1),总的时间复杂度为O(n * 1)
再次改进尝试:
def sample_1_3(x n):
if n == 0:
return 1
if n % 2 == 1:
return sample_1_3(x, n//2) * sample_1_3(x, n//2) * x
return sample_1_3(x, n//2) * sample_1_3(x, n//2)
上述代码时间复杂度,如何计算?
首先查看递归了多少次?可以将递归抽象成一颗满二叉树来表示,每个节点代表着一次递归并进行了一次乘法的操作,则递归的次数为节点的个数,所有节点的个数为一个公比为2等比数列的求和使用sum = 2^(m + 1) -1表示,x的n次方,需要递归的次数为sum,则递归
次数,将m使用n表示,忽略常数项-1,则m=logn -1, 得到sum = n -1,所以时间复杂度仍然为O(n)。
查看上述代码,去除冗余的部分,我们可以得到下面的代码:
def sample_1_4(x, n):
if n == 0:
return 1
t = sample_1_4(x, n//2)
if n % 2 == 1:
return t * t * x
return t * t
可以看到这里仅仅有一个递归调用,且每次都是n/2, 所以这里是log以2为底的对数次。 每次递归都是做了一次乘法操作, 时间复杂度为O(logn).
空间复杂度分析
概念: 是对一个算法在运行过程中占用内存空间大小的量度,记做S(n)=O(f(n)
空间复杂度(Space Complexity)记作S(n) 依然使用大O来表示。利用程序的空间复杂度,可以对程序运行中需要多少内存有个预先估计
常见问题
- 口那个键复杂度是否是可执行文件大小?
空间复杂度是考虑程序运行时占用内存的大小,而不是可执行文件的大小 - 空间复杂度是准确算出程序运行时所占内存?
空间复杂度是预先大体评估程序内存使用的大小。
空间复杂度是logn的情况确实有些特殊,其实是在递归的时候,会出现空间复杂度为logn的情况。