引子
一道算法题:“求出满足a+b+c=1000和a^2+b^2=c^2的所有a,b,c的自然数组合”。
首先可以想到的就是枚举法。
根据题意,a,b,c取最大范围,它们都是0到1000的数,所以可以得到下面的算法。
算法I
for a in range(1001):
for b in range(1001):
for c in range(1001):
if a+b+c==1000 and a**2+b**2==c**2:
print("a,b,c: %d,%d,%d" %(a,b,c))
上面的算法有三个循环的嵌套,可以简单的简化一下,通过第一个条件限定c的范围。
算法II
for a in range(1001):
for b in range(1001):
c=1000-a-b
if a**2+b**2==c**2:
print("a,b,c: %d,%d,%d" %(a,b,c))
算法介绍
概念
算法是独立存在的一种解决问题的方法和思想。
特性
- 输入:算法有0或者多个输入
- 输出:算法有1或者多个输出
- 有穷性:算法是在有限步骤和可接受的时间内解决问题的方法
- 确定性:算法的每一步都有确定的含义,没有二异性
- 可行性:算法可以用程序语言实现
时间复杂度与“大O记法”
对于抽象的算法,通常无法作出精确度量。这种情况下就要设法估计算法复杂性的量级。对于算法的时间和空间性质,最重要的是其量级和趋势,这些是代价的主要部分,而代价函数的常量因子可以忽略不计。据此,人们提出了“大O记法”。
“大O记法”
定义:对于单调的整数函数f,如果存在一个整数函数g和实常数c>0,使得对于充分大的n总有f(n)<=c·g(n),就说函数g是f的一个渐近函数(忽略常量因子),记为f(n)=O(g(n))。在n趋于无穷大的情况下,函数f的增长速度受到函数g的约束。
时间复杂度
定义:假设存在函数g,使得算法A处理规模为n的问题实例所用时间T(n)=O(g(n)),则称O(g(n))为算法A的渐近时间复杂度,即时间复杂度。
最优时间复杂度
算法运行最少需要多少的基本操作(研究意义不大)
平均时间复杂度
算法运行平均需要多少的基本操作(对算法的全面评价)
最坏时间复杂度
算法运行最多需要多少的基本操作(提供了保证在此种程度下一定能完成工作的复杂度)
实际中主要关注最坏时间复杂度
时间复杂度的计算规则
- 对于基本步骤和常数项,认为T(n)=O(1)
- 对于顺序结构,T(n)按照加法进行计算
- 对于循环结构,T(n)按照乘法进行计算
- 对于分支结构,T(n)取复杂度最大的情况
- 计算时间复杂度关注最高次项,忽略其他次要项和常数项
- 使用最坏时间复杂度准则
对算法I和算法II进行时间复杂度的计算
算法I
T(n)=n*n*n*2=n^3*2
忽略常数项
故,T(n)=O(n^3)
算法II
T(n)=n*n*2=n^2*2
忽略常数项
故,T(n)=O(n^2)