算法笔记
第一章、什么是算法
用计算机求解问题的步骤:
1.分析问题;
2.建立数学模型;
3.算法设计与选择;
4.算法表示;
5.算法分析;
6.算法实现;
7.程序测试及调试;
8.结果整理和文档编制。
1.1算法的定义:
算法( algorithm)是指在解决问题时,按照某种机械步骤一定可以得到问题结果(有解时给出问题的解,无解时给出无解的结论)的处理过程。
1.2 算法的3要素:
算法由操作、控制结构、数据结构3要素组成。
1.3 算法的基本特征:
有穷性、确定性、可行性、算法有零个或多个的输入、算法有一个或多个的输出
1.4 算法的基本性质:
目的性、分步性、有序性、有限性、操作性
1.5 算法在设计时的质量指标:
1.正确性;2.可读性;3.稳健性;4.高效率与低存储量需求。
1.5 算法的实现两种方法:
1.结构化方法;
2.面向对象方法:结构化方法总的指导思想是自顶向下、逐步求精、模块化;
面向对象步骤:
在给定的问题域中抽象地识别出类和对象。
识别这些对象和类的语义。
识别这些类和对象之间的关系。
实现类和对象。
1.6 从算法到实现:
1.数据类型的选择;
2.计算过程的差异;
3.结果输出的格式;
4.算法实现后的测试、调试
1.7 算法的描述:
1.自然语言;
2.流程图;
3.盒图;
4.PAD图;
5.伪代码;
6.程序设计语言
1.7.1 时间复杂度分析:
定义1:如果存在两个正常数c和n0,对于所有的n≥n0,有|f(n)|≤c |g(n)|,则记作f(n)=Ο(g(n))。
定义2:如果存在两个正常数c和n0,对于所有的n≥n0,有|f(n)|≥c |g(n)|,则记作f(n)=Ω(g(n))。
定义3:当 f(N)=Ο(g(N)) 且 f(N)=Ω(g(N))时,则记 f(N)=θ(g(N))。也就是说f(N)与g(N)同阶。
定义4:如果对于任意给定的ε≥0,都存在非负整数N0,使得当N≥N0时有f(N)≤εg(N),则称函数f(N)当N充分大时,比g(N)低阶,记为f(N)=o(g(N))。
定义5:若g(N)=o(f(N)), 即当N充分大时, f(N)的阶比g(N)高,则记f(N)= ω(g(N))。
1.7.2空间复杂度:
- 输人数据所占空间;
- 算法(程序)本身所占空间;
- 辅助变量所占空间。
1.8 NP完全问题
P类问题:所有可以在多项式时间内求解的判定问题构成P类问题。
NP类问题:所有的非确定性多项式时间可解的判定问题构成NP类问题。
第二章、迭代算法与蛮力算法
迭代法(iteration)也称“辗转法”,是一种不断用变量的旧值递推出新值的解决问题的方法。
蛮力法是基于计算机运算速度快这一特性,在解决问题时采取的一种“懒惰”策略。这种策略不经过(或者说是经过很少的)思考,把问题的所有情况或所有过程交给计算机去一一尝试,从中找出问题的解
第三章、分而治之算法
分治算法:分而治之算法(divide and conquer)的设计思想是,将一个难以直接解决的大问题,分割成几个规模较小的相似问题,以便各个击破,分而治之。
3.1分治法在每一层递归上都有3个步骤。
(1) 分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同
的子问题;
(2) 解决:若子问题规模较小而容易被解决则直接解,否则再继续分解为更
小的子问题,直到容易解决;
(3) 合并:将已求解的各个子问题的解,逐步合并为原问题的解。
3.2适合用分治策略的问题:
当求解一个输入规模为n且取值又相当大的问题时,用蛮力策略效率一般得不到保证。若问题能满足以下几个条件,就能用分治法来提高解决问题的效率。
(1)能将这n个数据分解成k个不同子集合,且得到k个子集合是可以独立求解的子问题,其中1<k≤n;
(2)分解所得到的子问题与原问题具有相似的结构,便于利用递归或循环机制;
(3)在求出这些子问题的解之后,就可以推解出原问题的解。
3.3 分治法的一般的算法设计模式如下:
Divide-and-Conquer(int n) //n为问题规模
{ if (n≤n0) //n0 为可解子问题的规模
{ 解子问题;
return(子问题的解);
}
for (i = 1 ; i <= k; i++) //分解为较小子问题p1,p2,……pk
yi = Divide-and-Conquer(|Pi|); //递归解决Pi
T = MERGE(y1,y2,...,yk); //合并子问题
return(T);
}
3.4典型二分法:
不同于现实中对问题(或工作)的分解,可能会考虑问题(或工作)的重点、难点、承担人员的能力等来进行问题的分解和分配。在算法设计中每次一个问题分解成的子问题个数一般是固定的,每个子问题的规模也是平均分配的。当每次都将问题分解为原问题规模的一半时,称为二分法。二分法是分治法较常用的分解策略,数据结构课程中的折半查找、归并排序等算法都是采用此策略实现的。
第四章、贪心算法(局部最优策略能导致产生全局最优解)
从问题的某一个初始解出发逐步逼近给定的目标,每一步都作一个不可回溯的决策,尽可能地求得最好的解。当达到某算法中的某一步不需要再继续前进时,算法停止。
第五章、动态规划
动态规划:最优化原理,创立了解决多阶段最优化决策的新方法——动态规划。
动态规划的基本思想:动态规划算法通常用于求解具有某种最优性质的问题。
5.1动态规划特点
在这类问题中,可能会有许多可行解。
每一个解都对应于一个值,我们希望找到具有最优值的解。
动态规划基本思想是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。
5.2 利用动态规划寻找最长公共子序列的步骤如下:
(1)先寻找最长公共子序列的长度。
(2)扩展寻找长度的算法来获得最长公共子序列。
设LCSLength(X,Y,i,j)表示X[1:i]与Y[1:j]的最长公共子序列的长度c[i,j],下面给出计算最长公共子序列长度的递归算法。
5.3 代码示例
int LCSLenth(char X[], char Y[], int i, int j)
{
if(i==0 || j==0)
return 0;
if(X[i] == Y[j])
return LCSLength(X,Y,i-1,j-1)+1;
else
return max(LCSLength(X,Y,i,j-1), LCSLength(X,Y,i-1,j));
}
5.4动态规划的两个基本要素:
- 最优子结构性质;2. 子问题重叠性质;
5.5动态规划的四个求解步骤:
- 分析最优子结构性质:是基础,也是关键。子问题的分解和对应的的子问题描述是关键;
- 递归地定义最优值:是动态规划算法的核心,它是最优解的规划过程;
- 以自底向上的方式计算出最优值:体现了动态规划算法的执行过程;
- 构造最优解:是可选步骤,只有问题要求构造最优解时才需要;
5.6三类典型问题的动态规划算法:
在第一类中,基于划分策略构造子问题最优值与原问题最优值的递推关系,其中最佳划分位置需要枚举,比如矩阵链式相乘问题;
在第二类中,基于减一策略构造子问题最优值与原问题最优值的递推关系,子问题规模般比原问题规模小一个单位,比如最长公共子序列、数字三角形、最大子段和、0-1背包等问题;
在第三类中,状态值不是直接表示待求解问题的目标值,相反,它定义了一个中间目标,然后通过中间目标值计算出原问题的最优解,比如最长递增子序列问题。
第6章、分支限界法(剪枝)
待续……