第一章 算法概论
1.1 算法与程序
算法:若干指令组成的有限集合。
四个性质:输入, 输入, 确定性(语法无二义性),有限性(指令有限)。
1.2 算法的复杂度分析
算法复杂度:时间和空间代价衡量。
一般分析时间复杂度较多,主要有三个时间复杂度分析,最好,平均,最坏,其中实践证明最坏时间复杂度最具有现实意义。T(n)=n的多项式(Time),n是问题规模。
当问题规模N趋近无穷大时,我们称为时间复杂度的渐进表达式。(数学理论基础是高等数学极限思想)。O(n)=n的多项式,n是问题规模。
NP完全性理论
P类问题 Polynomial 多项式时间内可解决的 判定性 问题。
NP类问题, None-Polynomial 在多项式时间内能够解的正确性, 一般是猜测+验证, 证明该问题是否可以在多项式时间内解决。
第二章 递归与分支策略
1. 递归
1.1 递归的定义
递归定义:简介或直接调用自身的方法的算法。
两个要素{ 边界条件,递归函数 }
适应问题:
(1)问题定义是递归的。(阶乘)
(2)数据结构是递归的。(二叉树的遍历)
(3)问题解决方法是递归的。(汉诺塔问题)
1.2 递归问题和算法复杂度分析
(1)阶乘函数
解释:原来问题规模为n,问题转化成n(n-1)
unsigned int factorial(unsigned int )
{
if(n==0)return 1;
return n*factorial(n-1);
}
(2)Fibonacci数列
无穷数列1,1,2,3,5,8,13,21,34,55......,递归定义
unsigned int fibonacci(unsigned int n)
{
if(n<1)return 1;
return fibonacci(n-1)+fibonacci(n-2);
}
(3)排列问题
(4)整数划分问题
(5)汉诺塔问题
总结: 递归问题都是在不断的减小原来问题的规模, 让原问题变得更小,直到临界条件。
但是, 递归问题用递归方法较为耗时,所以一般采用非递归方法,用一个栈来模拟递归,从而使运行速度加快(同时优化栈操作,尽可能减少栈操作,否则并不能加快速度)。
2. 分治
2.1 分治法基本思想
基本思想:将一个规模为n的问题,分解为k个规模较小的子问题,这些子问题相互独立且与原问题相同。
算法设计模式如下:
divide_and_conquer(P)
{
if(|P|<n0)adhoc(P);
divide P into smaller subinstances P1,P2,...Pk;
for(int i=1;i<=k;i++)
{
yi=divide_and_conquer(Pi);
}
return merge(y1,y2,y3...,yk);
}
解释:P是问题的规模,n0是阀值,当问题规模小于n0时,问题已经很容易解决了,直接可以用方法adhoc()解决。算法merge()是该分治算法合并子算法,用于将P的子问题P1,P...Pk,的解y1,y2,y3....yk,合并为P的解。
为了方便起见,将阀值n0设为1,且adhoc()解规模为1的问题耗费1个单位的时间。此外,再设将原问题分解为k个子问题以及用merge将k个子问题的解合并为原问题耗时。若问题规模P=n,则设
为时间复杂度公式:
解读:将原问题分解为k个规模n=n/m的,同时耗时合并。
分析渐进时间复杂度
方法一:主定理
分治时间<分割时间
,
分治时间=分割时间
,
分治时间>分割时间
,
方法二:定义函数递推。
2.2 各种例子
(1)二分搜索术
(2)合并排序
(3)快速排序
(4)Strassen矩阵乘法
减小子问题个数
(5)大整数乘法
减少子问题个数
(6)棋盘覆盖
设计一样的子问题
第三章 动态规划
第四章 贪心算法
第五章 回溯法-+
0
+