python学习:算法和时间复杂度
算法
什么是算法?
算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。
算法也可以说是我们为了解决问题而编写的程序,它能够对一定规范的输入,在有限时间内获得所要求的输出。
同一问题可用不同算法解决,而一个算法的质量优劣将影响到算法乃至程序的效率。算法分析的目的在于选择合适算法和改进算法。
一个算法的评价主要从时间复杂度、空间复杂度、正确性、可读性、健壮性(容错性)这几个方面来考虑。
算法的主要方法
在解决问题时,采用的方法不同,可能会有多种不同的算法。常用解决问题的方法有:
- 递推法:将复杂的庞大的计算过程转化为简单连续或重复的过程
- 递归法:递归函数,在函数中调用本身
- 分治法:将复杂问题逐步分解为较小问题,直到最后的小问题可简单解出
- 迭代法:也叫辗转法,是一种不断用变量的旧值递推新值的过程
- 回溯法:一种选优搜索法,按选优条件向前搜索,以达到目标
- 贪心算法:以当前情况为基础根据某个条件作最优选择,而不考虑各种可能的选择,以迭代的方法做出相继的贪心选择
- 动态规划法:将原问题分解为相似的子问题,在求解的过程中通过子问题的解求出原问题的解。
- 分支定界法:对有约束条件的最优化问题的所有可行解空间进行搜索。
如何评价算法的优劣呢?比较简单、直观的评价方式就是 算法的运行时间或占用的空间
时间复杂度
算法运行时间
- 影响因素:
- 软件因素:机器编译代码的速度
- 硬件因素:计算机硬件好坏
- 算法因素:算法程序代码
- 问题规模:需解决问题的规模大小
- 推导:
- 问题规模n条件下
- 算法运行总时间-->
- 每行代码运行时间之和-->
- 单行代码执行次数f(n)-->
- 大O复杂度表示法O(f(n))-->
- 复杂度公式T(n)=O(f(n))
求解步骤
1.找出算法中的基本语句:执行次数最多的那条语句
2.计算基本语句执行次数
3.推算执行次数数量级:保证最高次项正确
4.用大O表示
计算法则
- (1).对于一些简单的输入输出语句或赋值语句,近似认为需要O(1)时间
- (2).对于顺序结构,需要依次执行一系列语句所用的时间可采用大O下"求和法则"
- (3).对于选择结构,如if语句,它的主要时间耗费是在执行then字句或else字句所用的时间,需注意的是检验条件也需要O(1)时间
- (4).对于循环结构,循环语句的运行时间主要体现在多次迭代中执行循环体以及检验循环条件的时间耗费,一般可用大O下"乘法法则"
- (5).对于复杂的算法,可以将它分成几个容易估算的部分,然后利用求和法则和乘法法则技术整个算法的时间复杂度
- 求和法则:设T1(n)=O(f(n)),T2(n)=O(g(n)),则 T1(n)+T2(n)=O(max(f(n), g(n)))
- 乘法法则:设T1(n)=O(f(n)),T2(n)=O(g(n)),则 T1T2=O(f(n)g(n))
常见复杂度
- 常数阶O(1)
- 线性阶O(n)
- 平方阶O(n²)
- 对数阶O(logn)
- 线性对数阶O(nlogn)
a = 1
b = a
c = b
执行时间与问题规模n无关,时间复杂度为常数阶,记T(n)=O(1)
a = 0
b = 100
for i in range(n):
a += i
b -= i
执行时间与问题规模n相关,执行次数f(n)=2n+2,时间复杂度为线性阶,记T(n)=O(n)
x = 0
y = 1
for i in range(n):
x += i
for j in range(n):
y *= j
执行时间与问题规模n相关,执行次数f(n)=n^2+2,时间复杂度为平方阶,记T(n)=O(n^2)
i = 1
while i <= n:
i *= 2
执行时间与问题规模n相关,执行次数2^(f(n)-1)=n,时间复杂度为对数阶,记T(n)=O(logn)
for j in range(n):
i = 1
while i <= n:
i *= 2
执行时间与问题规模n相关,时间复杂度为线性对数阶,记T(n)=O(nlogn)
对时间复杂度的分析并不复杂,需要多多练习
拓展:其他时间复杂度
递归算法的时间复杂度(recursive algorithm time complexity):
总体时间复杂度O(每个递归函数时间复杂度T*depth递归深度)最好情况时间复杂度(best case time complexity):
算法在最好情况下执行代码的时间复杂度,运行时间最短的情况最坏情况时间复杂度(worst case time complexity):
算法在最坏情况下执行代码的时间复杂度,运行时间最长的情况平均时间复杂度(average case time complexity):
代码在所有可能情况下执行次数的加权平均值均摊时间复杂度(amortized time complexity):
在代码执行的所有复杂度情况中绝大部分是低复杂度,个别情况是高复杂度且发生具有时序关系时,可以将个别高复杂度均摊到低复杂度上。