这是我的算法分析与设计课程自己总结的一些知识点,应该不太全,记录一下
算法的特征:
输入,输出,确定性,有穷性,可行性
基本数据结构:
线性,树结构,图结构,集合
递归与分治
1、递归法
使用递归方法时须注意的问题:
(1) 递归调用函数必须在满足某个条件时能够退出该程序
(2) 递归调用由于使用堆栈,因此占用的存储空间会很大,且所花费的时间也很多,因而效率低下。
2、分治法
将一个规模比较大的问题分解成若干个规模较小的问题,然后将这些子问题的解合并解出整个问题的解。
分而治之算法(分解,解决,合并)
算法思想
为了解决一个大的问题,可以:1) 把它分成两个或多个更小的问题; 2) 分别解决每个小问题; 3) 把各小问题的解答组合起来,即可得到原问题的解答。小问题通常与原问题相似,可以递归地使用分而治之策略来解决。
分而治之方法很自然地导致了递归算法的使用。在许多例子里,这些递归算法在递归程序中得到了很好的运用。实际上,在许多情况下,所有为了得到一个非递归程序的企图都会导致采用一个模拟递归栈。不过在有些情况下,不使用这样的递归栈而采用一个非递归程序来完成分而治之算法也是可能的,并且在这种方式下,程序得到结果的速度会比递归方式更快。解决金块问题的分而治之算法(和归并排序方法就可以不利用递归而通过一个非递归程序来更快地完成
可以运用分而治之方法来解决排序问题,该问题是将n 个元素排成非递减顺序。分而治之方法通常用以下的步骤来进行排序算法:若n 为1,算法终止;否则,将这一元素集合分割成两个或更多个子集合,对每一个子集合分别排序,然后将排好序的子集合归并为一个集合。
选择排序算法时间复杂度O(n平方)
归并排序程序将花费(nlogn) 的时间。
快速排序时间复杂度:
T(n)=T(n-1)+O(n); [T(n)=C1n+T(n-1);T(1)=C2]
最好情况:
T(n)=2T(n/2)+O(n); [T(n)=C1n+2T(n/2);T(1)=C2](C1,C2为常数)
动态规划算法
动态规划算法的特点:
动态归化算法是将问题分解成若干个子问题,通过求解这些子问题的最优解来求整个问题的最优解。与分治法不同的是,这些子问题往往并不相互独立,不能将子问题的解作为最后问题的解。动态规划往往用于求解问题的最优解
例1:给定n个矩阵的连乘表达式,求其最少需要多少次乘法运算才能计算出乘法运算的结果
动态规划问题取决于两个重要的性质:
1、最优子结构性质:问题的最优解包含了其子问题的最优解。
2、子问题重叠性质:后续问题的求解可通过前面的子问题的求解结果计算出来。
因此可通过动态规划基本上可通过递归算法实现。
例2:设序列X={x1,x2,x3…,xm}, Y={y1,y2,y3,…,yn},求这两个序列的最长公共子序列Z。
设Z={z1,z2,z3,…zk},则必有下面的结论存在:
(1)如果xm=yn,说明xm或yn一定是最长公共子序列中的最后一个元素,即zk=xm=yn。同样可以得出{z1,z2,z3,…, zk-1}是序列Xm-1和Yn-1的最长公共子序列。
(2)如果xm≠yn且zk≠xm,说明xm不是Z中的一个元素,Z中的元素与X中的最后一个元素无关,因此Z是Xm-1与Yn的最长公共子序列。
(3)如果xm≠yn且zk≠yn,说明yn不是Z中的一个元素,Z中的元素与Y中的最后一个元素无关,因此Z是Xm与Yn-1的最长公共子序列。
贪心算法
贪心算法的基本要素:贪心选择和最优子结构
回溯法(系统性,跳跃性)
回溯法实际上是一种搜索问题的解的一种方法。所采用的方法一般为深度优先搜索法,所搜索的路径一般是沿树形结构进行搜索。在搜索过程中,首先会判断所搜索的树结点是否包含问题的解,如果肯定不包含,则不再搜索以该结点为根的树结点,而向其祖先结点回溯。否则进入该子树,继续按深度优先策略搜索。
在访问某一个结点时,是否访问其某一颗子树的判断标准是:
(1)该结点是否与其它结点之间有连接关系。
(2)如果有,是否该结点所用的颜色是否已经使用过。
(3)如果上述两个条件同时成立,则返回false.
(4) 如果上述条件均不成立,说明可以找到一种颜色使其与其它与该结点相连的结点的颜色不同,这样就可以继续访问下一层的结点。
(5)如果当前访问的结点所在的层数已经大于结点的个数,显然已经为每个节点分配了相应的颜色,可以输出这些颜色。
(6)同样在访问结点的下一棵子树时,其访问的方法与前面相同。此时,需要将前面访问的子树的所设置的颜色设置成0,以便访问下一个子树时给它安排新的颜色
寻找问题的解的一种可靠的方法是首先列出所有候选解,然后依次检查每一个,在检查完所有或部分候选解后,即可找到所需要的解。理论上,当候选解数量有限并且通过检查所有或部分候选解能够得到所需解时,上述方法是可行的。不过,在实际应用中,很少使用这种方法,因为候选解的数量通常都非常大(比如指数级,甚至是大数阶乘),即便采用最快的计算机也只能解决规模很小的问题。对候选解进行系统检查的方法有多种,其中回溯和分枝定界法是比较常用的两种方法。按照这两种方法对候选解进行系统检查通常会使问题的求解时间大大减少(无论对于最坏情形还是对于一般情形)。事实上,这些方法可以使我们避免对很大的候选解集合进行检查,同时能够保证算法运行结束时可以找到所需要的解。因此,这些方法通常能够用来求解规模很大的问题。
算法思想
回溯(ba c k t r a c k i n g)是一种系统地搜索问题解答的方法。为了实现回溯,首先需要为问题定义一个解空间( solution space),这个空间必须至少包含问题的一个解(可能是最优的)。下一步是组织解空间以便它能被容易地搜索。典型的组织方法是图或树。一旦定义了解空间的组织方法,这个空间即可按深度优先的方法从开始节点进行搜索。
回溯方法的步骤如下:
(1)定义一个解空间,它包含问题的解。
(2)用适于搜索的方式组织该空间。
(3)用深度优先法搜索该空间,利用限界函数避免移动到不可能产生解的子空间。
回溯算法的一个有趣的特性是在搜索执行的同时产生解空间。在搜索期间的任何时刻,仅保留从开始节点到当前E-节点的路径。因此,回溯算法的空间需求为O(从开始节点起最长路径的长度)
分支限界法
以广度优先或最小耗费方式搜索问题解的算法叫分支限界法
算法分析:
采用分支限界法求解问题的关键是先要建立一个约束条件,也就是剪枝的判断条件。显然从起点到达图中同一顶点的路径之和越短,其结果也就越符合求解要求,反之越长的结点所对应的子树也就应该从求解空间中剪去。
求解时应该建立一个小顶堆空间,用于存储活结点表,并在求解过程中不断的构建堆,直到处理完所有的结点。该堆中的结点表示从起点到该点的当前最短路径的结点编号,并保存其路径长度。
与回溯法不同的是,分支限界法的求解目标往往是找出满足约束条件的一个解,或者在满足约束条件的解中找出是某一目标函数值达到极大或者极小的解,而不是问题的所有解。
分支限界法的求解方式往往采用广度优先或者以最小耗费优先的方式搜索解空间树。
快速排序算法的性能取决于划分的对称性。
分支限界法分为两种:
队列式和优先队列式
队列式扩展结点的原则:
FIFO;
节点的优先级(查找一个具有最小耗费或最大收益的解);
回溯法和分支限界法是在蛮力法的基础上的一个改进。蛮力法是搜索所有的可能解,然后再评估这些解哪一个满足约束条件。而回溯法及分支限界法则每次只构造可能解的一部分,然后评估这个部分解。如果这个部分解有可能导致一个可行解,则对其进一步构造,否则就不必继续构造这个部分解,从而避免搜索所有的可能解。