《算法设计与分析》期末不挂科
Posted ZSYL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《算法设计与分析》期末不挂科相关的知识,希望对你有一定的参考价值。
考前知识点整理
我们学校开设的这门课,过于理论,实践太少,考试不会太难,一起学习,一起 不挂科!
但是算法平时一定要练哦!加油!
内容摘自老师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)
递归优缺点
优点:结构清晰,可读性强,而且容易用数学归纳法来证明算法的正确性,因此它为设计算法、调试程序带来很大方便。
缺点:递归算法的运行效率较低,无论是耗费的计算时间还是占用的存储空间都比非递归算法要多。
递归树方法
基于递归树的方法可以更好地猜测一个问题的解,并用替换方法证明这个猜测。
递归树的生成规则:
- 初始,递归树只有根结点,其值为W(m);
- 不断继续下述过程:
将函数项叶结点的迭代式W(mi)表示成二层子树;
用该子树替换该叶结点; - 继续递归树的生成,直到树中无函数项(只有初值)为止。
例题:解递归方程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)
- 其中a≥1,b>1为常数,f(n)是渐近正函数。
- 递归方程 T(n)=aT(n/b)+f(n) 描述了算法的运行时间,算法将规模为n的问题划分成a个子问题,每个子问题的大小为n/b,其中a、b是正常数。求解这a个子问题,每个所需时间为T(n/b)。函数f(n)表示划分子问题与组合子问题解的开销。
- 每个子问题n/b未必为整数,但用T(n/b)代替T(⌈n∕b⌉)和T(⌊n∕b⌋ )并不影响递归方程的渐近行为,因此我们在表达这种形式的分治算法时将略去向下取整函数和向上取整函数。
主定理
主定理解析
主定理举例
分治法
总体思想
将求出的小规模的问题的解合并为一个更大规模的问题的解,自底向上逐步求出原来问题的解。
分治法的设计思想是,将一个难以直接解决的大问题,
分割成一些规模较小的相同问题,以便各个击破,
分而治之。
凡治众如治寡,分数是也。
----孙子兵法
适用条件
分治法所能解决的问题一般具有以下几个特征:
- 该问题的规模缩小到一定的程度就可以容易地解决;
- 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;
- 利用该问题分解出的子问题的解可以合并为该问题的解;
- 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。
- 这条特征涉及到分治法的效率,如果各子问题是不独立的,则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然也可用分治法,但一般用动态规划较好。
归并排序
归并排序(merge sorting) 是分治法应用的一个实例,由以下三步组成:
(1)划分:将待排序n个元素的序列划分成两个规模为n/2的子序列。
(2)解决:用归并排序递归地对每一子序列排序。
(3)合并:归并两个有序序列,得到排序结果。
当划分的子序列规模为1时,递归结束。因为一个元素的序列被认为是有序的。
算法的复杂度分析
归并算法的改进
- MERGE-SORT算法将待排序集合一分为二,不停递归,直至排序集合只剩1个元素为止。然后不断合并2个排好序的数组段。
- 递归算法运行效率低,怎样从分治策略的机制入手,消除算法中的递归?
- 方案:首先将数组中相邻元素两两配对。用合并算法将他们排序,构成n/2组长度为2的排好序的子数组段,如此继续,直至整个数组排好序。
快速排序
快速排序由C. A. R. Hoare在1960年提出。
基本思想:
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
动态规划
算法总体思想
动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题。
但是经分解得到的子问题往往不是互相独立的。不同子问题的数目常常只有多项式量级。在用分治法求解时,有些子问题被重复计算了许多次。
如果能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,就可以避免大量重复计算,从而得到多项式时间算法。
动态规划基本步骤
1)找出最优解的性质,并刻划其结构特征。
2)递归地定义最优值。
3)以自底向上的方式计算出最优值。
4)根据计算最优值时得到的信息,构造最优解。
动态规划算法的基本要素
最优子结构
- 矩阵连乘计算次序问题的最优解包含着其子问题的最优解。这种性质称为最优子结构性质。
- 在分析问题的最优子结构性质时,所用的方法具有普遍性:首先假设由问题的最优解导出的子问题的解不是最优的,然后再设法说明在这个假设下可构造出比原问题最优解更好的解,从而导致矛盾。
- 利用问题的最优子结构性质,以自底向上的方式递归地从子问题的最优解逐步构造出整个问题的最优解。最优子结构是问题能用动态规划算法求解的前提。
同一个问题可以有多种方式刻划它的最优子结构,有些表示方法的求解速度更快(空间占用小,问题的维度低)。
重叠子问题
- 递归算法求解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。这种性质称为子问题的重叠性质。
- 动态规划算法,对每一个子问题只解一次,而后将其解保存在一个表格中,当再次需要解此子问题时,只是简单地用常数时间查看一下结果。
- 通常不同的子问题个数随问题的大小呈多项式增长。因此用动态规划算法只需要多项式时间,从而获得较高的解题效率。
备忘录方法
备忘录方法的控制结构与直接递归方法的控制结构相同(自顶向下),区别在于备忘录方法为每个解过的子问题建立了备忘录以备需要时查看,避免了相同子问题的重复求解。
0-1背包实例
最长公共子序列
矩阵连乘
分析最优解的结构
建立递归关系
递归的复杂性
计算最优值
DP求解的复杂度分析
构造最优解
贪心算法
贪心算法与分治法和动态规划算法的关系
1)分治法将原问题分解成独立的子问题,然后递归求解子问题,并组合成原问题的解。
2)动态规划应用于子问题不独立时,它的实质是分治思想和解决冗余,为避免重复计算,它将已经计算过的子问题存储起来,达到最优解决问题的目的。
3)贪心法与动态规划法和分治法类似,都是将问题分解为规模更小的、相似的子问题,并通过求解子问题产生一个最优解。
有些具有最优子结构性质的问题,可以用动态规划算法求解,但是用贪心算法更简单、更直接,且解题效率更高。
贪心算法的基本思想
贪心法的当前选择可能要依赖已经做出的所有选择,但不依赖于有待于做出的选择和子问题。因此贪心法自顶向下,一步一步地做出贪心选择。
贪心法总是做出在当前时刻看起来最优的决策,即希望通过局部最优决策导致问题的全局最优解。
特别说明:贪心法并不总是产生问题的全局最优解,但许多问题利用贪心法求解得到全局最优解。
贪心算法的基本要素
贪心选择(greedy-choice)的性质
- 利用贪心算法的第一步,是问题具有贪心选择的性质,通过局部最优选择(贪心),可以得到问题的全局最优解。
- 当考虑要做出哪一个选择时,我们会选择当前看起来最优的,而不考虑子问题的结果。这就是贪心算法和动态规划算法的不同之处。
- 在动态规划算法中,当我们在每一步做出选择时,这个选择通常会依赖于子问题的解。 因而,我们一般会按照自底向上的方式,求解的过程从较小的问题到较大的问题,最后解决原问题。
- 而在贪心算法中,我们首先会做出当前看起来最优的选择,然后解决选择之后出现的子问题。 贪心算法的选择可能取决于到目前为止所做的选择, 但不会依赖于未来的选择,也不会依赖于子问题的解。因此,采用贪心策略解问题的过程通常按照自顶向下的方式逐次进行贪心选择,将每一给定问题实例减少到更小问题实例。
最优子结构(optimal substructure)
- 如果问题的最优解中包含子问题的最优解,则问题展示了最优子结构。这个性质是评价应用动态规划以及贪心算法的基本性质。背包问题和活动选择问题都具有最优子结构性质。
- 在背包问题中,如果问题的一个最优解包含物品j,我们从最优装包中去掉物品j的一个权值w,那么,余下至多为W-w的容量,一定包括n-1个物品以及物品j的权值为wj-w的最优装包方式。
两个背包问题
背包问题与0-1背包问题的不同点在于,在选择物品装入背包时,可以只选择物品的一部分,而不一定要选择物品的全部。
- 尽管这两个问题很相似,但是背包问题可用贪心法求解, 而0-1背包问题却不能。
- 对于0-1背包问题,贪心选择之所以不能得到最优解是因为在这种情况下,它无法保证最终能将背包装满,部分闲置的背包空间使每公斤背包空间的价值降低了。
- 事实上,在考虑0-1背包问题时,应比较选择该物品和不选择该物品所导致的最终方案,然后再作出最好选择。由此就导出许多互相重叠的子问题。这正是该问题可用动态规划算法求解的另一重要特征。实际上动态规划算法的确可以有效地解0-1背包问题。
前缀码
二元前缀码:用0-1字符串作为代码表示字符,要求任何字符的代码都不能作为其它字符代码的前缀。
回溯算法
使用回溯法的问题特征:当需要找出问题的解集或者要求回答什么解是满足某些约束条件的最佳解时,往往要使用回溯法。
回溯法的基本做法是搜索,或是一种组织得井井有条的、能避免不必要搜索的穷举式搜索法。这种方法适用于解一些组合数相当大的问题。
搜索策略:回溯法在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解。如果肯定不包含,则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先策略搜索。
子集树的构造
0-1背包问题对应的解空间就是一棵子集树, 树中所有结点都可能成为问题的一个解。子集树中至多有2n个叶结点。
因此,任何算法遍历子集树所需运行时间为Ω(2n)。
排列树的构造
搜索树的构造
生成问题状态的方法
回溯法的基本思想
(1)针对所给问题,定义问题的解空间;
(2)确定易于搜索的解空间结构;
(3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。
常用剪枝函数:
用约束函数在扩展结点处剪去不满足约束的子树;
用限界函数剪去得不到最优解的子树。
n皇后问题
在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!种排列,因此将要构造的这棵树是一棵排列树。
使用剪枝函数的4皇后问题的状态空间树
- 在实际中,并不需要生成问题的整个状态空间,可以通过使用剪枝函数来杀死那些还没有生成其所有子结点的活结点。
- 下图是使用剪枝函数的4皇后问题的部分状态空间树,图中一个结点一旦被剪枝函数杀死,则用B做上记号。
- 在4皇后问题中,惟一开始结点为根结点1,路径为()。开始结点既是一个活结点,又是一个扩展结点, 它按照深度优先的方式生成一个新结点2,此时路径为(1),这个新结点2变成一个活结点和新的扩展结点,原来的扩展结点1仍然是一个活结点。
- 结点2生成结点3,但立即被杀死。于是,回溯到结点2,生成它的下一个结点8,且路径变为(1, 3)。
- 结点8成为扩展结点,由于它的所有子结点不可能导致答案结点,因此结点8也被杀死。回溯到结点2,生成它的下一个结点13,且路径变为(1, 4)。
n皇后问题及回溯算法
将4皇后问题推广到n皇后问题(n-queen problem),即找出n×n的棋盘上放置n个皇后并使其不能互相攻击的所有解。
设X =(x1, x2, …, xn)表示问题的解,其中xi表示第i个皇后放在第i行所在的列数。
- 解向量:(x1, x2, …, xn)
- 显约束:xi=1,2, … ,n
- 隐约束:
1)不同列:xixj
2)不处于同一正、反对角线:|i-j||xi-xj|
N-QUEEN算法代码分析
- 第1~2行进行初始化。
- 第3行的while 循环表示,对于所有行执行循环体,计算xk值。
- 在第5~6行的while循环中,对于每一个xk值,调用PLACE过程测试它的合法性, 即寻找满足约束条件的xk值。
- 第7行中,如果找到一个放置位置,则进一步测试,所求(x1, x2, …, xk)是否为问题的解,这只需判断k是否等于n。如果是问题的解,则输出(第9行), 否则通过赋值语句将k值增加1, 继续外层while 循环。
- 如果第7行的条件为假,则表明不存在合法的xk值,此时将k值减1(第12行),进行回溯。
分支限界法
分支限界法与回溯法的区别
(1)求解目标不同:回溯法的求解目标是找出解空间树中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出在某种意义下的最优解。
(2)搜索方式不同:回溯法以深度优先的方式搜索解空间树,而分支限界法则以广度优先或以最小耗费优先的方式搜索解空间树。
分支限界法基本思想
- 分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。
- 在分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生其所有儿子结点。在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。
- 此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。这个过程一直持续到找到所需的解或活结点表为空时为止。
常见的两种分支限界法
(1) 先进先出(first in first out,简称FIFO)分支限界法(FIFOBB)。在先进先出的分支限界法中,用队列作为组织活结点表的数据结构,并按照队列先进先出的原则选择结点作为扩展结点。
(2) 优先队列(priority queue,简称PQ)分支限界法(PQBB)。 在优先队列分支限界法中,用优先队列作为组织活结点表的数据结构,每个结点都有一个成本或价值,按照最大价值(greatest value)/最小成本(least cost)的原则选择结点作为扩展结点。
两种分支限界法的异同
先进先出状态空间树
优先队列状态空间树
当用优先队列作为组织活结点表的数据结构,并按照结点估值函数值的大小选择下一个扩展结点时,就得到0-1背包问题优先队列状态空间树。
组合优化问题
- 目标函数(极大化或极小化)
- 约束条件:解满足的条件
- 可行解:搜索空间满足约束条件的解
- 最优解:使得目标函数达到极大(或极小)的可行解
- 典型的组合优化问题有:
旅行商问题(TSP)、生产调度问题、0-1背包问题、装载问题、图着色问题、最大团问题等。
代价函数
- 计算位置:搜索树的结点
- 值:极大化问题是以该点为根的子树所有可行解的值的上界(极小化问题为下界)
- 性质:对极大化问题父结点代价不小于子结点的代价(极小化问题相反)
界
- 含义:当前得到可行解的目标函数的最大值(极小化问题相反)
- 初值:极大化问题初值为0(极小化问题为最大值)
- 更新:得到更好的可行解时
分支限界
停止分支回溯父结点的依据:
- 不满足约束条件
- 对于极大化问题,代价函数值小于当前界(对于极小化问题是大于界)。
界的更新:
对极大化问题,如果一个新的可行解的优化函数值大于(极小化问题为小于)当前的界,则把界更新为该可行解的值。
Sample Test
select question
- 当输入规模为 n 时,算法增长率最小的是 B,最大的是 C。
- 渐进算法分析是指 当规模逐步往极限方向增大时,对算法资源开销“增长率”上的简化分析
- 递归通常用 栈 来实现。
- 分治法的设计思想是将一个难以直接解决的大问题分割成规模较小的子问题,分别解决子问题,最后将子问题的解组合起来形成原问题的解。这要求原问题和子问题 问题规模不同,问题性质相同
- 对于 0-1 背包问题和背包问题的解法 0-1 背包问题不能用贪心算法求解,但可以使用动态规划或搜索算法求解,而背包 问题则可以用贪心算法求解
- 具有最优子结构的算法有 动态规划法、贪心算法、分治算法
- 关于回溯搜索法的介绍:
1)回溯法有“通用解题法”之称,它可以系统地搜索一个问题的所有解或任意解。
2)回溯法是一种既带系统性又带有跳跃性的搜索算法。
3)回溯算法在生成以上是关于《算法设计与分析》期末不挂科的主要内容,如果未能解决你的问题,请参考以下文章