第一章 算法引论
1、 如果存在正的常数和自然数N0,使得当N>= N0时有f(N)<=Cg(N),则称函数f(N)在N充分大时上有界,且g(N)是它的一个上界,记为f(N) = O(g(N))。还称f(N)的阶不高于g(N)的阶。
(1) O(f) + O(g) = O(max(f, g))
(2) O(f) + O(g) = O(f + g)
(3) O(f)O(g) = O(fg)
(4) 如果g(N) = O(f(N)),则O(f) + O(g) = O(f)
(5) O(Cf(N)) = O(f(N)),其中C是一个正的常数
(6) f = O(f)
2、 按照按照渐进阶从低到高的顺序排列以下表达式:4n2, logn, 3n, 20n, 2, n2/3。又n!应该排在哪一位?
2 , logn , n2/3 , 20n , 4n2 , 3n , n!
第二章 递归与分治策略
1、递归的概念:直接或间接地调用自身的算法称为递归算法。用函数自身给出定义的函数称为递归函数。
递归的优点:结构清晰,可读性强,易用数学归纳法来证明算法的正确性,为设计算法、调试程序带来很大方便。缺点:运行效率较低,耗费的计算时间多、占用的存储空间多。
解决方法:在递归算法中消除递归调用,使其转化为非递归算法。
具体实施:①采用一个用户定义的栈来模拟系统的递归调用工作栈。
②用递推来实现递归函数;③通过Cooper变换、反演变换能将一些递归转化为尾递归,从而迭代求出结果。(以上两种方法在时空复杂度上均有较大改善,但其适用范围有限。)
分治法所能解决的问题一般具有以下几个特征:
①该问题的规模缩小到一定的程度就可以容易地解决;
②该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质
③利用该问题分解出的子问题的解可以合并为该问题的解;
④该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。(能否利用分治法完全取决于问题是否具有这条特征,如果具备了前两条特征,而不具备第三条特征,则可以考虑贪心算法或动态规划。)
2、Hanoi塔问题(递归)
public static void hanoi(int n, int a, int b, int c) {
if(n > 0) {
hanoi(n-1, a, c, b);
move(a, b);
hanoi(n-1, c, b, a);
}
}
思考:如果塔的个数变为a,b,c,d四个,现要将n个圆盘从a全部移动到d,移动规则不变,求移动步数最小的方案。
void hanoi_basic_3(int n, char a, char b, char c)
{//把n个盘子从a柱子移动到b柱子
if(n > 0)
{
hanoi_basic_3(n - 1, a, c, b);
move(n, a, b);
hanoi_basic_3(n - 1, c, b, a);
}
}
void hanoi(int n, char a, char c, char b, char d, int C[])
{
int j=C[n]; //j个盘子使用四个柱子的移动方式
if(n > 0) {
hanoi(j, a, d, b, c, C);// 把j个盘子移动到d柱子上
hanoi_basic_3(n - j, a, c, b);// 把n-j个盘子移动到c柱子上(使用三个柱子的移动方式)
hanoi(j, d, c, a, b, C); // 把j个盘子移动到c柱子上 </