-
计算机算法五大特征:①输入,0个或多个;②输出,至少一个;③有限性,有穷性,有限时间内;④确定性,确切无歧义指令;⑤可行性,有效性。
-
分支限界法解最大团问题时,活结点表的组织形式是“最大堆”;解单源最短路径问题,是“最小堆”,解旅行售货员问题,是“最小堆”。
-
Huffman编码算法通过构建哈夫曼树实现,使用优先队列(最小堆)来合并节点,每次操作需要O(logn)时间,总共n个节点,因此总时间复杂度为O(nlogn)。
-
分治法(分治策略、最优子结构性质):(子问题独立不重复且方法相同)
快速排序(O(nlogn));实现循环赛日程表;二分搜索;归并排序;棋盘覆盖问题;选择问题;Strassen矩阵乘法;大整数乘法
-
回溯法:构建状态空间树(子集树O(2n),排列树O(n!)),以深度优先(“栈”后进先出LIFO)方式搜索解空间树,逐步探索并回溯,通过约束函数或界限函数剪枝无效分支。最大团问题;排列问题;n皇后问题;0/1背包问题(O(n2ⁿ));旅行售货员问题;图的m着色问题
-
动态规划法(重叠子问题、最优子结构性质、无后效性):分治思想,递归求解子问题,通过表储存解,自底向上or备忘录法求解。定义、构造、算出最优解。矩阵连乘问题;最长公共子序列算法;0/1背包问题;最大子段和问题(O(n));
-
分支限界法:队列式(先进先出FIFO)。构建状态空间树,广度优先or最佳优先搜索&最小耗费优先&最大效益优先,找到最优解,通过约束函数或界限函数剪枝无效分支。最大团问题;单源最短路径问题;0/1背包问题;旅行售货员问题
-
贪心法(贪心选择性质、最优子结构性质):最优子结构性质,自顶向下求解。哈夫曼编码问题(O(nlogn));单源最短路径问题(Dijkstra算法);最小生成树问题(Prim或Kruskal算法O(eloge))O(n²);(部分)背包问题(n(nlogn))。
-
分治法与动态规划法: 同:将待求解的问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。 异:适合于用动态规划法求解的问题,经分解得到的子问题往往不是互相独立的。而用分治法求解的问题,经分解得到的子问题往往是互相独立的。
-
动态规划基本步骤:(划分阶段——选择状态——确定决策并写出状态转移方程)
①分析最优解的性质,并刻画其结构特征。②递归地定义最优值。③以自底向上的方式或自顶向下的记忆化方法(备忘录法)计算出最优值。④根据计算最优值时得到的型芯,构造一个最优解。
基本思想:空间换时间
使用条件:满足最优子结构,满足无后效性,有重叠的子问题。
-
分支限界法与回溯法:
同:都是一种在问题的解空间树T中搜索问题解的算法。 异:(1)求解目标不同; (2)搜索方式不同; (3)对扩展结点的扩展方式不同; (4)存储空间的要求不同。
-
程序是 ( 算法 ) 用某种程序设计语言的具体实现。
-
算法的“确定性”指的是组成算法的每条(指令)是清晰的,无歧义的。
-
矩阵连乘问题的算法可由(动态规划)设计实现。
-
(贪心选择性质)是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。
-
快速排序算法是基于(分治策略) 的一种排序算法。
-
主定理法仅适用于分治策略导出的递归方程,且需严格满足形式 (T(n) = aT(n/b) + cn的k),其中:
-
常数 (a ≥ 1)(子问题个数非负);
-
常数 (b > 1)(子问题规模严格缩小);
-
(f(n)) 是渐进正函数(当 n 足够大时,(f(n) > 0),保证非递归部分有实际耗时)。
时间复杂度:a>b的k –> O(n的logba);
= –> O(n的klogbn);
< –> O(n的k)
-
渐进符号概念回顾: f(n) = O(g(n)):f(n)的增长率 ≤ g(n)的增长率(上界) f(n) = Ω(g(n)):f(n)的增长率 ≥ g(n)的增长率(下界) f(n) = θ(g(n)):f(n)的增长率 = g(n)的增长率(紧确界)
-
-
拉斯维加斯算法可能找不到解,但一旦找到,解一定是正确的;而蒙特卡罗算法总能找到解,但解可能不正确。
-
剪枝函数(约束函数和限界函数)用于提前终止不可能产生解的搜索分支。回溯法的核心策略之一是 “剪枝”—— 在搜索解空间树时,通过剪枝函数判断当前分支是否可能导出有效解。
-
左剪枝:当前容量>C(最大容量); 右剪枝:回溯rp(剩余物品总价值)+cp(当前价值) < bestv(当前最优价值)
-
确定性算法:分治法、动态规划法贪心法、分支限界法。
-
随机算法:数值概率算法、蒙特卡罗、拉斯维加斯、舍伍德等算法。
-
算法是指解决问题的(一种方法或一个过程)。
-
从分治法的一般设计模式可以看出,用它设计出的程序一般是(递归算法)。
-
问题的( 最优子结构性质)是该问题可用动态规划算法或贪心算法求解的关键特征。
-
数值概率算法常用于(数值问题)的求解。
-
计算一个算法时间复杂度通常可以计算)循环次数、基本操作的频率或计算步)。
-
利用概率的性质计算近似值的随机算法是(数值概率算法),运行时以一定的概率得到正确解的随机算法是(蒙特卡罗算法)。
-
解决 0/1 背包问题可以使用动态规划、回溯法和分支限界法,其中不需要排序的是(动态规划法),需要排序的是(回溯法,分支限界法)。
-
使用回溯法进行状态空间树裁剪分支时一般有两个标准:约束条件和目标函数的界,N 皇后问题和 0/1 背包问题正好是两种不同的类型,其中同时使用约束条件和目标函数的界进行裁剪的是(0/1背包问题),只使用约束条件进行裁剪的是(n皇后问题)。
-
回溯法是一种既带有(系统性)又带有(跳跃性)的搜索算法。
-
分支限界法是一种既带有(系统性)又带有(跳跃性)的搜索算法。
-
回溯法搜索解空间树时,常用的两种剪枝函数为(约束函数)和(界限函数)。
-
快速排序算法的性能取决于(划分的对称性)。
-
Prim 算法利用(贪心)策略求解(最小生成树)问题,其时间复杂度是O(n²)。
-
图的 m 着色问题可用(回溯)法求解,其解空间树中叶子结点个数是(mⁿ),解空间树中每个内结点的孩子数是(m)。
-
递归:自顶向下,栈
-
P类问题包含在NP类问题中。
-
用动态规划策略求解最长公共子序列问题: (1)给出计算最优值的递归方程。 (2)给定两个序列X={B,C,D,A},Y={A,B,C,B},请采用动态规划策略求出其最长公共子序列,要求给出过程。 答: (1)
-
动态规划求解0/1背包问题:
V(0, j) = 0(0个物品),V(i, 0) = 0(承重量0) V(i, j) = V(i-1, j) 第 i 个物品不能装入, j < wi (超重) V(i, j) = max { vi + V(i-1,j-wj) , V(i-1, j) } j > wi (不超重) i在最优子集中,j-wj:失去空间 i不在最优子集中
-
1.背包问题的贪心算法
void Knapsack (int n, float M, float v [], float w [], float x []) { Sort (n, v, w); int i; for (i=1; i<=n; i++) x[i]=0; float c=M; for (i=1; i<=n; i++) { if (w[i]>c) break; x[i]=1; c - =w[i];### // 更新剩余容量:剩余容量减去当前物品重量 } //若还有物品未处理,取剩余容量占该物品重量的比例 if (i<=n) x[i]=c/w[i]; ### // 取最后一个物品的部分 }2.最大子段和: 动态规划算法
int MaxSum (int n, int a []) { int sum=0, b=0; //sum存储当前最大的b[j], b存储b[j] for(int j=1; j<=n; j++) { if (b>0) b+= a[j] ; else b=a[j]; ### //一旦某个区段和为负,则从下一个位置累和 if(b>sum) sum=b;### //更新全局最大和 } return sum; }3.快速排序
template<class Type> void QuickSort (Type a [], int p, int r) { if (p<r) { int q=Partition (a, p, r);### QuickSort (a,p,q-1); //对左半段排序 ### QuickSort (a,q+1,r); //对右半段排序 ### } }4.排列问题
Template <class Type> void perm (Type list [], int k, int m) { //产生[list[k:m]的所有排列 if(k==m)### { //只剩下一个元素 for (int i=0; i<=m; i++) cout<<list[i]; cout<<endl; } else //还有多个元素待排列,递归产生排列 for (int i=k; i<=m; i++)### { swap(list[k],list[i]); perm (list, k+1; m);### swap(list[k], list[i]); } }5.给定已按升序排好序的n个元素a[0:n-1],现要在这n个元素中找出一特定元素x。 据此容易设计出二分搜索算法:
template<class Type> int BinarySearch (Type a [], const Type& x, int l, int r) { while (l<=r) { ### int m = ((l+r)/2);### if (x == a[m]) return m; if (x < a[m]###) r = m-1; else l = m+1; } return -1; } 6、合并排序描述如下: template<class Type> void Mergesort (Type a [], int left, int right) { if (left<right) {### int i=(left+right)/2;### Mergesort (a, left, i); Mergesort (a, i+1, right);### Merge(a,b, left,i,right);//合并到数组b Copy(a,b, left,right ); //复制到数组a } }7、以下是计算x的m的值的过程
int power (x, m) {//计算xm的值并返回。 y= (1); i=m; While #(i-- >0) y=y*x; #(Return y); }