算法绪论(Algorithm)
一、算法初步
1 算法的五大特性
- 输入:一个算法有零个或者多个输入
- 输出:一个算法有一个或多个输出
- 有穷性:一个算法必须在执行有限步数之后结束,且每一步需要在有穷时间内完成
- 确定性:每条指令必须有确切的含义,对于相同的输入只能得到相同的输出
- 可行性:算法可执行
2 算法的四个要求
- 正确性
- 可读性
- 健壮性
- 高效率与低存储量
3 算法的描述方法
- 自然语言
- 流程图
- 程序设计语言
- 伪代码----算法语言
4 算法设计的一般步骤
理解问题–>预测所有可能输入–>确定 解的类型、数据结构、算法设计技术–>设计并描述算法–>跟踪–>分析效率–>循环分析直到满意
5 算法执行时间相关因素
主要为:
-
算法选用的策略
-
问题的规模
基本操作:指该操作重复执行次数和算法的运行时间成正比。
二、非递归算法分析:
对非递归算法时间复杂性的分析,关键是建立一个代表算法运算时间的表达式,然后用渐进符号表示这个求和表达式
1 仅依赖于“问题规模”的时间复杂度
例1: 交换i和j的内容:
Temp = i; i = j; j = Temp;
//算法时间复杂度为O(1)。
结论:如果算法的执行时间不随问题规模n的增加而增长,即使算法中有上千条语句,其执行时间只不过是一个较大的常数。
例2:变量计数:
int x = 0, y = 0;
for(int k = 1; k <= n; k++){
x++;
}
for(int i = 0; i <= n; i++){
for(int j = 0; j <= n; j++){
y++;
}
}
//算法时间复杂度为O(n^2)
x = 1;
for(i = 1; i <= n; i++)
for(j = 1; j <= i; j++)
for(k = 1; k <= j; k++)
x++;//频度最大的语句
//算法时间复杂度为O(n^3)
结论:当有若干循环语句是,时间复杂度是由嵌套层数最多的循环语句中最内层语句的频度f(n)决定的。
2 算法时间复杂度与输入实例的初始状态有关
例3: k-选择算法 (现在还不懂这是个什么算法,后续学了来这里填坑,也欢迎大家指点!)
此时需要分析T(n,k),分别计算最好,最坏情况下的时间复杂度,若需计算平均时间复杂度需要“加权”
3 Conclusion:
非递归算法分析的一般步骤
- 确定算法问题规模;
- 找出关键操作;
- 分析该关键操作是否仅仅依赖于问题规模;
- 若是,直接建立代表关键操作执行次数的求和表达式,并求解、用渐进符号表示。
- 若不是,分别对该算法的最好,最坏和平均情况的时间复杂度进行分析。
KEY:建立代表关键操作执行次数的求和表达式,并求解、用渐进符号表示。
三、递归算法分析(!!!)
分析方法:
KEY: 根据递归过程建立递推关系式。
1 猜测技术
对递推关系式估计一个上限,然后数学归纳法证明其正确
例4:分析二路归并排序算法的时间复杂性
T
(
n
)
=
{
1
n
=
2
2
T
(
n
/
2
)
+
n
n
>
2
T(n) = \begin{cases}1 \quad n=2\\2T(n/2)+n \quad n>2\end{cases}
T(n)={1n=22T(n/2)+nn>2
说明:在长度为n的情况下,算法代价是序列长度为n/2时代价的两倍加上n。
分三种猜测情况进行归纳证明(P14页证明):
1.O(n^2) 2.O(cn) 3.O(nlogn)
2 扩展递归技术
扩展意思是:将递推关系式等式右边的项根据递推式子进行替换
扩展递归就是:扩展+扩展+扩展+…直到可求
-
迭代法
例5:求N!
//分析: 构造算法中的两个步骤: // (1) N! = N*(N-1)! // (2) 0! = 1, 1! = 1 int fact(int n){ if(n == 0 || n == 1) return 1; else return n*fact(n-1); }
分析:递归方程为:T(n) = T(n-1) + O(1),其中O(1)为进行一次乘法操作。
计算:
T ( n ) = T ( n − 1 ) + O ( 1 ) = T ( n − 2 ) + O ( 1 ) + O ( 1 ) = T ( n − 3 ) + O ( 1 ) + O ( 1 ) + O ( 1 ) = . . . = T ( n − ( n − 1 ) ) + ( n − 1 ) ∗ O ( 1 ) = n ∗ O ( 1 ) = O ( n ) \begin{aligned} T(n) &= T(n-1) + O(1) \\ &= T(n-2) + O(1) + O(1)\\ &= T(n-3) + O(1) + O(1) + O(1)\\ &=...\\ &= T(n-(n-1)) + (n-1)*O(1)\\ &= n*O(1) = O(n)\\ \end{aligned} T(n)=T(n−1)+O(1)=T(n−2)+O(1)+O(1)=T(n−3)+O(1)+O(1)+O(1)=...=T(n−(n−1))+(n−1)∗O(1)=n∗O(1)=O(n)
例6: Hanoi塔问题:Hanoi(A, C, n) //n个盘子A到C if n = 1 then move(A, C) else Hanoi(A, B, n-1) move(A, C) Hanoi(B, C, n-1)
则n个盘子工作量为:
T(n) = 2 T(n-1) + 1
T(1) = 1
计算得 T(n) = 2^n - 1
-
换元迭代法
例6:分析下列递推式的时间复杂度:
T ( n ) = { 7 n = 1 2 T ( n / 2 ) + 5 n 2 n > 1 T(n) = \begin{cases} 7 \quad n=1\\ 2T(n/2)+5n^2 \quad n>1 \end{cases} T(n)={7n=12T(n/2)+5n2n>1
分析:本题使用换元迭代法,设n = 2^k计算:
T ( n ) = 2 T ( n / 2 ) + 5 n 2 = 2 ( 2 T ( n / 4 ) + 5 ( n / 2 ) 2 ) + 5 n 2 = 2 ( 2 ( 2 T ( n / 8 ) + 5 ( n / 4 ) 2 ) + 5 ( n / 2 ) 2 ) + 5 n 2 = 2 k T ( 1 ) + 2 k − 1 5 ( n 2 k − 1 ) 2 + . . . + 2 ∗ 5 ( n 2 ) 2 + 5 n 2 = 7 n + 5 n 2 ∑ i = 0 k − 1 1 2 i = 7 n + 5 n 2 ( 2 − 1 2 k − 1 ) = 10 n 2 − 3 n ≤ 10 n 2 = O ( n 2 ) \begin{aligned} T(n) &= 2T(n/2) + 5n^2 \\ &=2(2T(n/4) + 5(n/2)^2) + 5n^2\\ &=2(2(2T(n/8)+5(n/4)^2)+5(n/2)^2) + 5n^2\\ &=2^kT(1)+2^{k-1}5(\frac{n}{2^{k-1}})^2+...+2*5(\frac{n}{2})^2 + 5n^2\\ &=7n+5n^2\sum_{i=0}^{k-1}\frac{1}{2^i}\\ &=7n+5n^2(2-\frac{1}{2^{k-1}})\\ &=10n^2-3n\\ &\leq10n^2=O(n^2)\end{aligned} T(n)=2T(n/2)+5n2=2(2T(n/4)+5(n/2)2)+5n2=2(2(2T(n/8)+5(n/4)2)+5(n/2)2)+5n2=2kT(1)+2k−15(2k−1n)2+...+2∗5(2n)2+5n2=7n+5n2i=0∑k−12i1=7n+5n2(2−2k−11)=10n2−3n≤10n2=O(n2)
(小小的记录:Markdown语法仅支持KaTex(LaTex的渲染器),故align不可操作,可使用aligned) -
差消法化简高阶递推方程
这个暂时挖个坑,学明白了来填!
3 通用分治递推法
这个公式咋来的咱也不知道,之后学到补上!
T
(
n
)
=
{
c
n
=
1
a
T
(
n
/
b
)
+
c
n
k
n
>
1
T(n) = \begin{cases}c \quad n=1\\aT(n/b)+cn^k \quad n>1\end{cases}
T(n)={cn=1aT(n/b)+cnkn>1
利用各个参数可得下列定理:
T
(
n
)
=
{
O
(
n
log
b
a
)
a
>
b
k
O
(
n
k
log
b
n
)
a
=
b
k
O
(
n
k
)
a
<
b
k
T(n)= \begin{cases}O(n^{\log_b^a}) \quad a>b^k\\O(n^k\log_b^n) \quad a=b^k\\O(n^k) \quad a<b^k\end{cases}
T(n)=⎩⎪⎨⎪⎧O(nlogba)a>bkO(nklogbn)a=bkO(nk)a<bk
四、常用算法时间复杂度排序(!!!)
我用3D计算器画了几根图像,应该能说明大部分问题:
同时,以下九种算法时间复杂度最常用,其关系为:
O(1)<O(logn)<O(n)<O(nlogn)<O(n^2)<O(n^3)<O(2^n)<O(n!)<O(n^n)
五、算法的后验分析(Posteriori)
后验分析指时间分析,转换成程序并上机实验
一般步骤:
- 明确实验目的
- 决定度量算法效率方法
- 决定输入样本,生成实验数据(样本规模、范围、格式)
- 运行程序,记录实验数据
- 分析数据