赞
踩
我们学校开设的这门课,过于理论,实践太少,考试不会太难,一起学习,一起 不挂科!
但是算法平时一定要练哦!加油!
内容摘自老师PPT及复习资料,感谢!
感兴趣的话可以参考 算法竞赛、小白学DP(动态规划) 学习相关代码的具体实现(Java版)
算法是指解决问题的一种方法或一个过程。
算法是若干指令的有穷序列。
对每一个输入实例算法都能终止,并给出正确输出。
(1)输入:有外部提供的量作为算法的输入。
(2)输出:算法产生至少一个量作为输出。
(3)确定性:组成算法的每条指令是清晰,无歧义的。
(4)有限性:算法中每条指令的执行次数是有限的,执行每条指令的时间也是有限的。
(可行性)
程序是算法用某种程序设计语言的具体实现。
程序可以不满足算法的性质(4)(有限性)。
例如操作系统,是一个在无限循环中执行的程序,因而不是一个算法。
操作系统的各种任务可看成是单独的问题,每一个问题由操作系统中的一个子程序通过特定的算法来实现,当子程序得到输出结果后便终止。
这个好像要考(* ̄︶ ̄)
(1)问题的陈述。
(2)模型的选择。
(3)算法的设计。
(4)算法的程序实现。
(5)算法分析。
算法复杂性 = 算法所需要的计算机资源
1、考虑算法的好坏主要有以下几点:
(1)执行算法所耗费的时间。
(2)执行算法所耗费的存储空间,其中主要考虑辅助存储空间。
(3)算法应易于理解,易于编码,易于调试等。
2、影响程序运行时间的主要因素 :
(1)程序的输入。
(2)由编译系统所产生的代码程序的质量。
(3)执行程序的计算机机器指令的性能与速度。
(4)程序所依据的算法的时间复杂度。
3、算法的复杂性测度主要有两个方面:
(1) 时间复杂度 T(n)
(2) 空间复杂度 S(n)
其中n是问题的规模(输入大小)。
算法的复杂性取决于:
(1)求解问题的规模N;
(2)具体的输入数据I;
(3)算法本身的设计
可操作性最好且最有实际价值的是最坏情况下的时间复杂性。
递归的概念:
直接或间接地调用自身的算法称为递归算法。
用函数自身给出定义的函数称为递归函数。
说明:
1、递归程序必须有终止条件。否则就总是自我调用,永不终止。
2、尽管递归程序在执行时间上往往比非递归程序要付出更多的代价,但有很多问题的数学模型或算法设计方法本来就是递归的。
3、用递归过程来描述它们不仅非常自然,而且证明该算法的正确性要比相应的非递归形式容易得多。
4、递归过程的优点:结构清晰,程序易读,正确性容易证明 。
5、缺点:运行的效率比较低 、花时间。
6、实现递归过程的关键在于为过程的递归调用建立一个先进后出型调用堆栈 。一个过程要有一个相应的递归调用堆栈。
欧几里得算法:已知两个非负整数m,n,且m>n>0,求这两个数的最大公因子。
欧几里得得出本算法基于这样一种观察,两个整数m和n的最大公因子等于n与m mod n的公因子。欧几里得算法如下:
GCD (m,n)
1 if n=0
2 then return m
3 return GCD (n,m mod n)
优点:结构清晰,可读性强,而且容易用数学归纳法来证明算法的正确性,因此它为设计算法、调试程序带来很大方便。
缺点:递归算法的运行效率较低,无论是耗费的计算时间还是占用的存储空间都比非递归算法要多。
基于递归树的方法可以更好地猜测一个问题的解,并用替换方法证明这个猜测。
递归树的生成规则:
例题:解递归方程T(n)=3T(n/4)+cn2。假设n为4的幂。
递归树的构造过程如下:
分析:
图(a)表示T(n)。
图(b)表示对T(n)进行扩展,形成与递归方程等价的一棵树。cn2表示树的根,即递归顶层的开销。根的三棵子树为小一级的递归方程T(n/4)。
图( c )表示对T(n/4)的进一步展开。根据递归方程,继续展开树中的每个结点,直到问题规模变成1,每个开销为T(1)。
图(d)表示最终结果树。树的高度是log4n,深度为log4n+1。
例题: T(n)=2T(n/2)+n-1
T(n)=kn-(2k-1)=nlogn-n+1=O(nlogn)
主方法(master method)为我们提供了解如下形式递归方程的一般方法。
T(n)=aT(n/b)+f(n)
将求出的小规模的问题的解合并为一个更大规模的问题的解,自底向上逐步求出原来问题的解。
分治法的设计思想是,将一个难以直接解决的大问题,
分割成一些规模较小的相同问题,以便各个击破,
分而治之。
凡治众如治寡,分数是也。
----孙子兵法
分治法所能解决的问题一般具有以下几个特征:
归并排序(merge sorting) 是分治法应用的一个实例,由以下三步组成:
(1)划分:将待排序n个元素的序列划分成两个规模为n/2的子序列。
(2)解决:用归并排序递归地对每一子序列排序。
(3)合并:归并两个有序序列,得到排序结果。
当划分的子序列规模为1时,递归结束。因为一个元素的序列被认为是有序的。
快速排序由C. A. R. Hoare在1960年提出。
基本思想:
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题。
但是经分解得到的子问题往往不是互相独立的。不同子问题的数目常常只有多项式量级。在用分治法求解时,有些子问题被重复计算了许多次。
如果能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,就可以避免大量重复计算,从而得到多项式时间算法。
1)找出最优解的性质,并刻划其结构特征。
2)递归地定义最优值。
3)以自底向上的方式计算出最优值。
4)根据计算最优值时得到的信息,构造最优解。
最优子结构
同一个问题可以有多种方式刻划它的最优子结构,有些表示方法的求解速度更快(空间占用小,问题的维度低)。
重叠子问题
备忘录方法的控制结构与直接递归方法的控制结构相同(自顶向下),区别在于备忘录方法为每个解过的子问题建立了备忘录以备需要时查看,避免了相同子问题的重复求解。
1)分治法将原问题分解成独立的子问题,然后递归求解子问题,并组合成原问题的解。
2)动态规划应用于子问题不独立时,它的实质是分治思想和解决冗余,为避免重复计算,它将已经计算过的子问题存储起来,达到最优解决问题的目的。
3)贪心法与动态规划法和分治法类似,都是将问题分解为规模更小的、相似的子问题,并通过求解子问题产生一个最优解。
有些具有最优子结构性质的问题,可以用动态规划算法求解,但是用贪心算法更简单、更直接,且解题效率更高。
贪心法的当前选择可能要依赖已经做出的所有选择,但不依赖于有待于做出的选择和子问题。因此贪心法自顶向下,一步一步地做出贪心选择。
贪心法总是做出在当前时刻看起来最优的决策,即希望通过局部最优决策导致问题的全局最优解。
特别说明:贪心法并不总是产生问题的全局最优解,但许多问题利用贪心法求解得到全局最优解。
贪心选择(greedy-choice)的性质
最优子结构(optimal substructure)
背包问题与0-1背包问题的不同点在于,在选择物品装入背包时,可以只选择物品的一部分,而不一定要选择物品的全部。
二元前缀码:用0-1字符串作为代码表示字符,要求任何字符的代码都不能作为其它字符代码的前缀。
使用回溯法的问题特征:当需要找出问题的解集或者要求回答什么解是满足某些约束条件的最佳解时,往往要使用回溯法。
回溯法的基本做法是搜索,或是一种组织得井井有条的、能避免不必要搜索的穷举式搜索法。这种方法适用于解一些组合数相当大的问题。
搜索策略:回溯法在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解。如果肯定不包含,则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先策略搜索。
子集树的构造
0-1背包问题对应的解空间就是一棵子集树, 树中所有结点都可能成为问题的一个解。子集树中至多有2n个叶结点。
因此,任何算法遍历子集树所需运行时间为Ω(2n)。
排列树的构造
搜索树的构造
(1)针对所给问题,定义问题的解空间;
(2)确定易于搜索的解空间结构;
(3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。
常用剪枝函数:
用约束函数在扩展结点处剪去不满足约束的子树;
用限界函数剪去得不到最优解的子树。
在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n后问题等价于在n×n格的棋盘上放置n个皇后,任何2个皇后不放在同一行或同一列或同一斜线上。
4皇后问题:棋盘上的行和列从1到4编号,同时也给皇后从1到4编号。由于每一个皇后应放在不同的行上,假设皇后i放在第i行上,因此4皇后问题可以表示成4元组(x1, x2, x3, x4), 其中xi(i=1, 2, 3, 4)表示皇后i所放置的列号。
显式约束条件是Si={1, 2, 3, 4},i=1, 2, 3, 4。在这种情况下,解空间为4^4个4元组组成。
隐式约束条件是没有两个xi相同(即所有皇后必须在不同列上),且满足不存在两个皇后在同一条对角线上。加上隐式约束条件,问题的解空间可进一步减小。此时,解空间大小为4!,因为所有解都是4元组的一个置换。
可以用一棵树表示4皇后问题的解空间。 由于4皇后问题的解空间为4!种排列,因此将要构造的这棵树是一棵排列树。
将4皇后问题推广到n皇后问题(n-queen problem),即找出n×n的棋盘上放置n个皇后并使其不能互相攻击的所有解。
设X =(x1, x2, …, xn)表示问题的解,其中xi表示第i个皇后放在第i行所在的列数。
(1)求解目标不同:回溯法的求解目标是找出解空间树中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出在某种意义下的最优解。
(2)搜索方式不同:回溯法以深度优先的方式搜索解空间树,而分支限界法则以广度优先或以最小耗费优先的方式搜索解空间树。
(1) 先进先出(first in first out,简称FIFO)分支限界法(FIFOBB)。在先进先出的分支限界法中,用队列作为组织活结点表的数据结构,并按照队列先进先出的原则选择结点作为扩展结点。
(2) 优先队列(priority queue,简称PQ)分支限界法(PQBB)。 在优先队列分支限界法中,用优先队列作为组织活结点表的数据结构,每个结点都有一个成本或价值,按照最大价值(greatest value)/最小成本(least cost)的原则选择结点作为扩展结点。
当用优先队列作为组织活结点表的数据结构,并按照结点估值函数值的大小选择下一个扩展结点时,就得到0-1背包问题优先队列状态空间树。
停止分支回溯父结点的依据:
界的更新:
对极大化问题,如果一个新的可行解的优化函数值大于(极小化问题为小于)当前的界,则把界更新为该可行解的值。
1)回溯法有“通用解题法”之称,它可以系统地搜索一个问题的所有解或任意解。
2)回溯法是一种既带系统性又带有跳跃性的搜索算法。
3)回溯算法在生成解空间的任一结点时,先判断该结点是否可能包含问题的解,如果肯定不包含,则跳过对该结点为根的子树的搜索,逐层向祖先结点回溯。
1)分支限界法中,活结点一旦成为扩展结点,就一次性产生其所有儿子结点,在这些儿子结点中,那些导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子加入 活结点表中。
2)回溯法和分支限界法都是在解空间树上搜索问题解的方法。
3)回溯法和分支限界法都可以用来解决组合优化问题。
分治算法 动态规划算法 贪心算法 有最优子结构
替换法、 递归树方法、主方法是求解递归方程
效率依赖于:满足显约束的值的个数、计算约束函数的时间、计算限界函数的时间。
最优子结构、构造最优解、定义最优解。
当所给的问题是从n个元素的集合中找出满足某种性质的子集时,相应的解空间树称为子集树(subset tree)。
有2^n个子集。
排列数的构造
为了构造出所有n!种排列,可以设一个具有n个元素的数组。第k个位置的候选解的集合就是那些不在前k-1个元素的部分解中出现的元素集合。
O(n^2)
1~N从A移动到B,C作为辅助
等价于:
1,1~N-1从A移动到C,B为辅助
2,把N从A移动到B
3,1~N-1从C移动到B,A为辅助
void hanoi(int n, int A, int B, int C){
if (n > 0) {
hanoi(n-1,A,C,B);
move(n,A,B);
hanoi(n-1,C,B,A);
}
}
依赖于:产生x[k]的时间,产生显约束的x[k]值的个数,计算上界函数约束的所有x[k]的个数,计算约束函数的时间
构造最优解、算出最优解、定义最优解
0/1背包问题不是。
子问题不能够重复、子问题的解可以合并、原问题和子问题使用相同的方法解。
单源最短路径问题、最小花费生成树问题、背包问题。
动态规划、回溯法、分支限界法
动态规划算法以自底向下的方式求解最优解
最早开始时间:可以增大资源的利用率。
最早结束时间(更合理):可以使下一个活动尽早开始。
①刻画最优解结构、②递归定义最优解的值、③计算最优解的值、④根据计算结果,构造最优解。
①问题的陈述。
②模型的选择。
③算法的设计。
④算法的程序实现。
⑤算法分析。
构造最优解、算出最优解、定义最优解
算法:指在解决问题时,按照某种机械步骤一定可以得到问题结果的处理过程。通俗讲,算法就是解决问题的方法或过程。
特征:
1.输入:有零个或多个外部量作为算法的输入。
2.输出:算法产生至少一个量或作为输出
3.确定性:组成算法的每条指令是清晰的,无歧义的
4.有限性 :算法中每条指令的执行次数有限,执行每条指令的时间也有限
5.可行性
考虑算法的好坏主要有以下几点:
1、执行算法所耗费的时间。
2、执行算法所耗费的存储空间,其中主要考虑辅助存储空间。
3、算法应易于理解,易于编码,易于调试等。
(1)该问题的规模缩小到一定的程度就可以容易地解决;
(2)该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;
(3)利用该问题分解出的子问题的解可以合并为该问题的解; (4)该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。
(1) 刻画问题最优解的结构
(2) 递归定义最优解的值
(3) 自底向上的计算问题最优解的值
(4) 根据计算的结果,构造问题最优解
(1) 求解目标不同:回溯法的求解目标是找出解空间树中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出在 某种意义下的最优解。
(2) 搜索方式的不同:回溯法以深度优先的方式搜索解空间树,而分支限界法则以广度优先或以最小耗费优先的方式搜索解空间树。
定义:一个直接或间接调用自身的算法。
优点:结构清晰,程序易读,正确性容易证明。
缺点:运行的效率比较低、花时间。
针对所给问题,定义问题的解空间;
确定易于搜索的解空间结构;
以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。
子集树:O(2n) 2n个叶子结点 2n+1-1个结点。
排列树:O(n!)n!个叶子结点。
在问题的解空间中,按深度优先遍历策略,从根节点出发搜索解空间树。算法搜索至解空间的任意一个节点时,先判断该节点是否包含问题的解。如果肯定不包含,跳过对以该节点为根的子树的搜索,逐层向其祖先节点回溯,否则进入该子树,继续深度优先搜索。
相同点:二者要求原问题具有最优子结构,都是将问题分而治之分解成若干个规模较 小的子问题;
不同点:分治法将原问题分解成独立的子问题,然后递归求解子问题,并组合成原问题的解。而动态规划应用于子问题不独立时,它的实质是分治思想和解决冗余,为避免重复计算,它将已经计算过的子问题存储起来,达到最优解决问题的目的。
(1) 先进先出(first in first out,简称 FIFO)分枝限界法。在先进先出的分枝限界法中, 用队列作为组织活结点表的数据结构,并按照队列先进先出的原则选择结点作为扩展结点。
(2) 优先队列(priority queue,简称 PQ)分枝限界法。在优先队列分枝限界法中,用优先队列作为组织活结点表的数据结构,每个结点都有一个成本或价值,按照最大价值 (greatest value)/最小成本(least cost)的原则选择结点作为扩展结点。
(1)队列式(FIFO)分支限界法:按照队列先进先出(FIFO)原则选取下一个节点为扩展节点。
(2)优先队列式分支限界法:按照优先队列中规定的优先级选取优先级最高的节点成为当前扩展节点。
1)分治法将原问题分解成独立的子问题,然后递归求解子问题,并组合成原问题的解。
2)动态规划应用于子问题不独立时,它的实质是分治思想和解决冗余,为避免重复计算,它将已经计算过的子问题存储起来,达到最优解决问题的目的。
3)贪心法与动态规划法和分治法类似,都是将问题分解为规模更小的、相似的子问题,并通过求解子问题产生一个最优解。
有些具有最优子结构性质的问题,可以用动态规划算法求解,但是用贪心算法更简单、更直接,且解题效率更高。
贪心算法与动态规划算法的主要区别所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是利用贪心算法求解最优解的第一个基本要素,也是贪心算法与动态规划算法的主要区别。
差异点:动态规划算法通常以自底向上的方式解各子问题,而贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每做一次贪心选择就将所求问题简化为规模更小的子问题。
贪心法自顶向下,一步一步地做出贪心选择。希望通过局部最优决策导致问题的全局最优解。
具有贪心选择的性质以及最优子结构。
哈夫曼编码:哈夫曼提出的贪心算法可以构造最优前缀编码,这样产生的编码称为哈夫曼编码。
都是在问题的解空间上搜索问题解的算法。
(1)求解目标不同:回溯法的求解目标是找出解空间树中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出在某种意义下的最优解。
(2)搜索方式不同:回溯法以深度优先的方式搜索解空间树,而分支限界法则以广度优先或以最小耗费优先的方式搜索解空间树。
分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。
在分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生其所有儿子结点。在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。
此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。这个过程一直持续到找到所需的解或活结点表为空时为止。
(1)针对所给问题,定义问题的解空间(对解进行编码);
(2)确定易于搜索的解空间结构(按树或图组织解) ;
(3)以广度优先或以最小耗费(最大收益)优先的方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。
1)用约束函数在扩展结点处剪去不满足约束的子树;
2)用限界函数剪去得不到最优解的子树。
请给出矩阵连乘问题的文字描述,然后用数学符号和公式表达出来。
递归方程和约束函数(递归终止条件)是递归的两个要素。
递归算法是一种直接或者间接地调用自身的算法。
递归算法解决问题的特点:
(1) 递归就是在过程或函数里调用自身。
(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
(3) 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。
(4) 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序。
特点:
1、该问题的规模缩小到一定的程度就可以容易解决
2、该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质
3、利用该问题分解出子问题解可以合并为该问题解
(1)刻画最优解的结构。
(2)递归定义最优解的值。
(3)自底向上(或自顶向下)方式计算最优解的值。
(4)根据计算的结果,构造问题最优解。
(1)划分阶段:按照问题的时间或空间特征,把问题分为若干个阶段。在划分阶段时,注意划分后的阶段一定要是有序的或者是可排序的,否则问题就无法求解。
(2) 确定状态和状态变量:将问题发展到各个阶段时所处于的各种客观情况用不同的状态表示出来。当然,状态的选择要满足无后效性。
(3) 确定决策并写出状态转移方程:因为决策和状态转移有着天然的联系,状态转移就是根据上一阶段的状态和决策来导出本阶段的状态。所以如果确定了决策,状态转移方程也就可写出。但事实上常常是反过来做,根据相邻两个阶段的状态之间的关系来确定决策方法和状态转移方程。
(4) 寻找边界条件:给出的状态转移方程是一个递推式,需要一个递推的终止条件或边界条件。
1、执行算法所耗费的时间。
2、执行算法所耗费的存储空间,其中主要考虑辅助存储空间。
3、算法应易于理解,易于编码,易于调试等。
如果问题的最优解包含子问题的最优解,则问题展示了最优子结构。
递归是重复调用函数自身实现循环。 迭代是函数内某段代码实现循环。
迭代与普通循环的区别是:
循环代码中参与运算的变量同时是保存结果的变量,当前保存的结果作为下一次循环计算的初始值。
1)对算法某些特定输入,估算该算法所需的内存空间和运行时间。
2)为了建立衡量算法优劣的标准,用比较同一类问题的不同算法。
(1)当所给的问题是从n个元素的集合S中找出满足某种性质的子集时,相应的解空间树称为子集树。这类子集树通常有2n个叶结点,遍历子集树需O(2n)计算时间。
(2)当所给的问题是确定n个元素满足某种性质的排列时,相应的解空间树称为排列树。这类排列树通常有n!个叶结点。遍历排列树需要O(n!)计算时间。
在扩展结点处,先生成其所有的儿子结点(分支),然后再从当前的活结点表中选择下一个扩展结点。为了有效地选择下一扩展结点,加速搜索的进程,在每一个活结点处,计算一个函数值(限界),并根据函数值,从当前活结点表中选择一个最有利的结点作为扩展结点,使搜索朝着解空间上有最优解的分支推进,以便尽快地找出一个最优解。
1、将n个元素分成大致相等的两部分。
2、取A(⌊n/2⌋)与v进行比较。
3、如果相等,则找到v,返回v所在位置,算法终止;
4、如果v<A(⌊n/2⌋),则在数组的左半部分继续查找v;如果v>A(⌊n/2⌋),则在数组的右半部分继续查找v。
5、当所查找的区间为0时,表示v不在数组中,返回查找不成功标志0。
1)步骤:
①划分:将待排序n个元素的序列划分成两个规模为n/2的子序列。
②解决:用归并排序递归地对每一子序列排序。
③合并:归并两个有序序列,得到排序结果。
当划分的子序列规模为1时,递归结束。因为一个元素的序列被认为是有序的。
2)归并算法描述:归并排序的关键操作是归并两个已排序的子序列的过程。用过程MERGE(A,p,q,r)表示归并两个有序序列A[p…q]和A[q+1…r]。当过程MERGE(A,p,q,r)执行完成后A[p…r]中包含的元素有序。
3)归并排序算法描述:我们将利用MERGE作为排序算法的子过程,利用MERGE-SORT对子数组A[p…r]中的元素进行排序。
解:由递归方程可得,a=4,b=2 且 f(n)=n。因此,
GCD(n,m)
If m=0
Return n
Return( GCD m n mod m)
T(n)= O(1)… n=2
T(n)= 7T(n/2)+O(n2)…n>2
10. 自然地导出递归的斐波那契过程 F(n)
F(n)
1 if n≤2
2 then return 1
3 return F(n-1)+F(n-2)
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); //对右半段排序
}
}
分析冒泡排序法BUBBLE-SORT(A)的最佳情况和最坏情况。
- 当输入数组正好为升序时,出现最佳情况,第4行语句不执行。
- 当输入数组为降序时,出现最差情况,第4行语句执行n(n-1)/2次。
bool Queen::Place(int k)
{ //检查x[k]位置是否合法
for (int j=1;j<k;j++)
if ((abs(k-j)==abs(x[j]-x[k]))||(x[j]==x[k])) return false;
return true;
}
void Queen::Backtrack(int t)
{
if (t>n) sum++;
else
for (int i=1;i<=n;i++) {
x[t]=i;
if (约束函数) Backtrack(t+1);
}
}
void Clique::Backtrack(int i) // 计算最大团
{
if (i > n) { // 到达叶结点
for (int j = 1; j <= n; j++) bestx[j] = x[j];
bestn = cn; return;}
// 检查顶点 i 与当前团的连接
int OK = 1;
for (int j = 1; j < i; j++)
if (x[j] && a[i][j] == 0) { // i与j不相连
OK = 0; break;}
if (OK ) { // 进入左子树
x[i] = 1; cn++;
Backtrack(i+1);
x[i] = 0; cn--; }
if (cn + n - i > bestn) { // 进入右子树
x[i] = 0;
Backtrack(i+1); }
}
2. 写出用动态规划解矩阵链乘问题的递归定义和最优解值的伪代码程序。
3. 写出哈夫曼编码的过程
理论加实践缺一不可,二者决定你走的深度与高度。
加油!
淦!
一直有粉丝想要PDF版,方便考试进行复习,今天分享给大家。
公众号:风口IT猪的成长录,后台回复:算法考试,即可获取下载链接。
直接下载,省时间:download,积分很多人都没有,csdn只能设置最低价1.9(平台提走1块),不能设置免费下载。
私信我,但可能回复不及时…
文章分享出来后,深受读者好评,感谢您的支持!
我今年刚刚上岸两电一邮,大家如有考研问题的可以与我私信交流。
付费专栏:原价49.9,限时9.9
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。