研究生复试 复习 算法分析

第一章

  1. 算法的定义:一组有穷的规则,它规定了某一类型问题的一系列计算方法。
  2. 算法的重要特性:1.确定性、2.可行性、3.输入、4.输出、5.有限性。
    确定性:算法的每一种运算必须确定,没有二义性。比如:1/0之类的运算不允许存在。
    可行性:算法的每一种运算在理论上课由人通过纸笔在有限时间内演算。
    输入:每个算法允许有0个或多个输入,这些量是在算法开始前给出的,在一个特定的集合内。
    输出:每个算法允许有1个或多个输出,这些是与输入有某种特定关系的量。
    有限性:算法必须在有限的时间内结束。
  3. 算法的基本内容:1.设计算法、2.表示算法、3.确认算法、4.分析算法、5.测试程序
  4. 算法分析目的:为了可以知道为完成一项任务所设计的算法的优劣,从而促使人们设计出更好的算法。
  5. 算法的全面分析分为两个阶段:事前分析、时候测试。
    事前分析:求出该算法的时间限界函数(时间复杂度、空间复杂度)
    事后测试:收集该算法的执行时间和占用空间的统计(作时空分布图)
    时间复杂度:用来描述算法随着输入规模增加、运算时间增长速率的统计量。
  6. 从计算时间上,可将算法分为两大类:多项式时间算法、指数时间算法。
    多项式时间算法:可以由多项式函数来计算时间限界的算法。
    指数时间算法:只能由指数函数来计算时间限界的算法。
  7. 频率计数:计算机执行程序中某一条语句的次数。

第二章

  1. 递归算法:一种自身调用自身或间接调用自身的算法。
  2. 大致可将递归通过思想分为两类:基于归纳法的递归称为递归算法、基于分治思想的递归称为分治算法。
  3. 系统在实现递归函数的调用时,应使用栈的方式管理调用递归函数时的返回的地址。
  4. 值的回传方式:两次值传送方式、地址传送方式。
    1)两次值传送方式:按照指定类型为变参设置存储空间,在执行函数调用时,将实参值传送给变参,在返回时将变参的值传给实参。
    2)地址传送方式: 在内部将变参设置成一个地址,在执行函数调用时,首先执行地址传送即将实参的地址传送给变参,在函数执行过程中,对变参的操作实际上变为对所对应地址的操作。
  5. 递归算法:基础步、归纳步
  6. 计算阶乘函数n!f(n) = f(n-1)+1 —>>O(n)
  7. 快速幂
//非递归
int quick_pow(int a,int b){//a^b
	int cnt = 1;
	while(b){
		if(b&1) cnt *=a;
		a*=a;
		b>>=1;
	}
	return cnt;
}
//递归
int quick_pow(int a,int b){//a^b
	int cnt = 1;
	if(b){
		cnt = quick_pow(a,b/2);
		cnt *= cnt;
		if(b&1) cnt*=a;
	}
	return cnt;
}

//O(logn)
  1. 插入排序 O(n^2) 稳定 栈深度n
  2. 多项式 递归 提取X化简,O(n) 站深度n
  3. 汉诺塔问题
void hmove(char a, char b, char c, int n){
    if(n == 0){
        return ;
    }
    hmove(a, c, b, n - 1);                     //前n - 1块从a移动到b上
    printf("%c -> %c\n", a, c);                //我自己移动一块从a -> c
    ans++;                                     //我移动了几次?
    hmove(b, a, c, n - 1);                     //最后把 n - 1块从b移动到c上
}//f(n) = 2f(n-1)+1;
 
//只能先移动到相邻的柱子上
void hmove2(char a, char b, char c, int n){
    if(n == 0){
        return ;
    }
    hmove2(a, b, c, n - 1);                    //把前n - 1块通过b移动到c上
    ans2++;                                    //把最后一块移动到b上
    printf("%c -> %c\n", a, b);
    hmove2(c, b , a, n - 1);                  //把n - 1 块通过b移动到a上
    ans2++;                                   //把最后一块移动到c上
    printf("%c -> %c\n", b, c);
    hmove2(a, b, c, n - 1);                   //把剩下的n - 1块通过b移动到c上
}//f(n) = 3f(n-1)+2;
  1. 分治法:分而治之,将问题分解成若干子问题,子问题的处理方法又与原问题相同。分为:划分步、治理步、组合步。 T(n)=kT(n/k)+bn -->T(n) = n+bnlogk(n) --> O(nlogk(n))
  2. 二分法
int find_2(int l,int r,int x){
	int m;
	while(l<r){
		m = (l+r)>>1;
		if(a[m] < x) l = m+1;
		else r = m;
	
	}
	return l;
}//O(logn)
``
  1. 归并排序 自上向下 稳定 O(nlogn)

第三章

  1. 贪心算法:在每一轮的循环中,通过少量的局部的计算,力争去找到一个局部最优解,而不考虑整体是否达到最优。
  2. 贪心求解背包问题:value/weight sort 非最佳算法;
    比如:WSUM = 7, P1 = 10,W1 = 5; P2 = 6,W2 = 4; P3 = 5,W3 = 3;
  3. 最短路径算法
    迪杰斯特拉算法 O(n^2)不可处理带负权值边 单源点
    弗洛里达 O(n^3) 多源点
    福特 O(VE) 可求负权边
  4. 最小生成树:
    Prim(普里姆算法) 取点 稠密图 O(n^2)选用邻接矩阵
    Kruskal(克鲁斯卡尔算法) 取边 疏散图 O(vlogv)选用邻接表 并查集

第四章

  1. 动态规划:是解决多阶段决策过程的方法。多阶段决策过程指的是它的活动过程不仅可以分成若干个阶段,而且在任意一个阶段以后的行为都仅仅依赖上一个阶段的过程状态,而与上个阶段之前的阶段没有关系。 具有马尔科夫性(后效性)
  2. 每一个多阶段决策过程都可以用多段图模型求解。
  3. 0/1背包问题 O(n^2)
  4. 最长公共子序列 LCS
    dp[i][j] : s1[0:i]与s2[0:j]的LCS
    则有DP方程 if (s1[i] == s2[j] ) dp[i][j] = dp[i-1][j-1]+1 else dp[i][j] = max(dp[i][j-1],dp[i-1][j])
    打印通过多开一个记录数组通过递归打印。
  5. 编辑距离 dp[i][j] = min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+bool(s[i]==s[j]))
  6. 区间DP POJ 1141 POJ1390

第五章

  1. 回溯算法:是一种选优搜索法,按选优条件向前搜索,以达到目标。回溯法采用试错的思想,它尝试分步的去解决一个问题。在分步解决问题的过程中,当它通过尝试发现现有的分步答案不能得到有效的正确的解答的时候,它将取消上一步甚至是上几步的计算,再通过其它的可能的分步解答再次尝试寻找问题的答案。

  2. 使用回溯算法对于问题的解空间进行深度搜索时,通常有两种搜索算法:递归回溯、迭代回溯。
    递归回溯:使用递归函数对于解空间进行DFS的回溯算法

  3. 0/1背包问题 DFS.

  4. 上界函数 用于剪除不包括最优解的子树

  5. 完全子图:给定无向图 G(v,e) U(v’,e’)当v’属于v,e’属于e,且对于图U任意两个节点都可以直接相连,U是G的完全子图,也可以说图U是图G的一个团体当且仅当图U不包括在更大的完全子图中时。

  6. 图G的最大团体指的是包含图G节点数最多的团体

  7. 找到最大团体算法 DFS

第六章

  1. 随机化算法:在算法中使用了随机函数,且随机函数的返回值直接或者间接的影响了算法的执行流程或执行结果。
    优点:1.所需要消耗的计算时间与空间开销,通常会小于一个问题的已知的最好的确定性算法。2.迄今为止的所有随机算法,他们的实现都比较简单,比较容易理解。
  2. 随机化算法分类:
    A. 数值随机化算法 近似解 精度随时间增加而增加 随机数产生器
    B. 蒙特卡洛算法 不确定是否为准确解 获得正确解的概率和时间正相关 大素数判定方法(根据:费马小定理。如果正整数N是素数,对于所有小于N的正整数A都有 A^(N-1)%N == 1)
    C. 拉斯维加斯算法 不确定能否找到,但一定是正确解 找到正确解概率和时间正相关 字符串查询RK算法
    D. 谢伍德算法 正确解 情况:当一个算法最坏和平均相差过大可以用 消除最坏情况和特定实例的关联 快排,K小数

第七章

  1. DFS BFS
  2. 无向图的割点:节点集合S是节点集合V的子集,如果删去S集合会使得图G变成非连通图,那么就称节点S是图G的割点集。如果S中只有一个节点,则称为割点。
  3. 如果再一个无相连通图没有割点,那么我们称它为双连通图。
  4. 连通图:任意两点之间存在路径
  5. 连通分量:无向图中最大连通图即为连通分量,连通图只有一个连通分量就是它自身。 Tarjan算法可求 O(E+V) DFS+栈实现
  6. 强连通图:有向图中任意两个节点直接互有路径。
  7. 简单通路:通路中所有的顶点互不相同。初级通路必为简单通路,但反之不真。
  8. 割点定理:A.深度优先搜索树中,节点V的任何一个子孙节点都不能通过向后边达到节点V的祖先。那个这个点就是割点。B.深度有限搜索树中,根节点至少有两个以上的孩子节点,根就是割点。
  9. 割点的寻找:Tarjan算法 时间戳思想
  10. 网络的最大流问题
    c(a,b) >= f(a,b) 容量约束
    f(a,b) = -f(b,a) 斜对称
    f(a,a) = 0 流量守恒
    EK 算法
1是源点 M是汇点,朴素EK
void EK(){
19     //从1出发,不断找可以到达m的增广路
20     int ans = 0;
21     while(true){
22         //EK算法的核心是通过bfs不断查找增广路,同时建立反向弧
23         //每次循环都要对v数组和p数组进行清空,因为是意图查找一条新的增广路了
24         memset(p, 0, sizeof(p));
25         memset(v, 0, sizeof(v)); 
26         queue<int> q;
27         q.push(1);
28         v[1] = INF;
29         //每次只找一条增广路,同时修改c[i][j]的值 
30         while(!q.empty()){
31             int f = q.front();
32             q.pop();
33             for(int i = 1; i <= m; i++){
34                 if(v[i] == 0 && c[f][i] > 0){        //v[i]原本是记录增广路实时的残量最小值,v[i]==0代表这个点还没有走过,且从p到i的残量大于0说明通路 
35                     v[i] = min(v[f], c[f][i]);        //实时更新v[i]的值,v[f]存储1条增广路中i点前所有水管残量的最小值,v[i]为该条增广路到i点为止,路径上的最小残量 
36                     p[i] = f;                        //p[i]实时保存i点的前驱节点,这样就当i==m时整条增广路就被记录下来 
37                     q.push(i);                        //将i点入队 
38                 }
39             } 
40         }
41         if(v[m] == 0) break;                          //如果v[m]==0则代表找不到增广路了(中途出现了c[i][j]==0的情况) 
42         ans += v[m];
43         int temp = m;
44         while(p[temp] != 0){                        //类似并查集的查操作,不断查上一个元素且将剩余残量减去最小残联,反向弧增加最小残量 
45             c[p[temp]][temp] -= v[m];
46             c[temp][p[temp]] += v[m];
47             temp = p[temp];
48         } 
49     } 
50     printf("%d\n", ans); 
51 }
  1. 二分图匹配
  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值