why?
数据结构和算法是什么?答曰:兵法!(内功)
算法是独立存在的一种解决问题的方法和思想。
算法的特征:
- 输入:算法具有0个或多个输入
- 输出:算法至少有1个或多个输出
- 有穷性:算法在有限的步骤之后会自动结束而不会无限循环,且每一个步骤可以在可接受的时间内完成。
- 确定性:算法中的每一步都有确定的含义,不会出现二义性。
- 可行性:算法的每一步都是可行的,也就是说每一步都能够执行有限的次数完成。
示例
1.代码:
# 算法引入
import time
# 问题描述:
"""如果a+b+c=N, 且a^2+b^2=c^2 (a,b,c 为自然数)
如何求出所有a、b、c可能的组合?"""
# 测试程序运行的时间
def cal_time(func):
def run(*args, **kwargs):
start = time.time()
func(*args, **kwargs)
end = time.time()
print("一共花了多少时间:", end-start)
return run
# 1.枚举法
@cal_time
def enum1(num):
for a in range(0, num):
for b in range(0, num):
for c in range(0, num):
if a+b+c==num and a**2 + b**2 == c**2:
print("a, c, b: %d, %d, %d" %(a, b, c))
# 时间复杂度:T = 1000 * 1000 * 1000 * 2
# 如果是2000则,T = 2000 * 2000 * 2000 *2
# 有 T(n) = (n^3) * 2
# 故将2看成常数,就有T(n) = (n^3) * k
#简化为 T(n) = n^3 (可以看出对于同一类问题,T与n的取值有关系,效率随着n的改变而改变。(大O表示法))
# 2.枚举法:算法改进
@cal_time
def enum2(num):
for a in range(0, num): # 执行n次
for b in range(0, num): # 执行n次
c = num - a - b # 执行1次
if a**2 + b**2 == c**2: # 分支结构,可能进入分支执行1次,也可能不进入分支(执行0次),故为max(1, 0)
print("a, c, b: %d, %d, %d" %(a, b, c))
# 时间复杂度:
# T(n) = n * n * (1 + max(1, 0) ) # 循环结构相乘,顺序结构相加,分支结构取最大
# = n^2 * 2
# = O(n^2) # 时间复杂度,省略次要项与常数项
def main():
# 取大N为1000
num = 1000
# enum1(num)
# 输出结果:
# a, c, b: 0, 500, 500
# a, c, b: 200, 375, 425
# a, c, b: 375, 200, 425
# a, c, b: 500, 0, 500
# 一共花了多少时间: 120.98069882392883
enum2(num)
# 输出结果:a, c, b: 0, 500, 500
# a, c, b: 200, 375, 425
# a, c, b: 375, 200, 425
# a, c, b: 500, 0, 500
# 一共花了多少时间: 1.2593419551849365
if __name__ == "__main__":
main()
2.时间复杂度与大O表示法
对于算法的优劣,最直观的就是执行时间。但是这种方法要基于同一个环境下,不同的机器上显然没有可比性。虽然有机器差别,但是对于同样的代码,每台机器执行的基本运算数量大体相同。即:可以把代码执行的基本运算数量记为时间复杂度。
3.最坏时间复杂度
对于同样的算法,处理的数据不同,效率不同,打个比方:对一组数据进行排序,很显然对有序的数据(有序的数据就是它的最理想情况)执行的就是比对无序的(最坏的情况)快。由此引入了以下的概念:
- 算法完成工作最少需要多少基本操作,即最优时间复杂度(即最理想的情况下)
- 算法完成工作最多需要多少基本操作,即最坏时间复杂度
- 算法完成工作平均需要多少基本操作,即平均时间复杂度
主要关注:最坏时间复杂度和最优时间复杂度
时间复杂度的几条基本计算规则:
- 基本操作,即只有常数项,认为其时间复杂度为O(1)
- 顺序结构,时间复杂度按加法进行计算
- 循环结构,时间复杂度按乘法进行计算
- 分支结构,时间复杂度取最大值
- 判断一个算法的效率时,往往只需要关注操作数量的最高次项,其他次要项和常数项可以忽略
- 在没有特殊说明时,我们所分析的算法的时间复杂度都是指最坏时间复杂度
4.常见时间复杂度
常见时间复杂度之间的关系