递归是指函数、过程、子程序在运行过程中直接或间接调用自身而产生的重入现象。
递归算法的主要表现形式:过程或函数在定义自身的同时对自身进行调用
适合用递归方法求解的问题:(1)有一个初始状态;(2)后续的情况可有前面的状态推出
基本思想:先定义问题的解空间,然后在问题的解空间树中,按深度优先策略,从根节点出发搜索解空间树。算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先的策略进行搜索。这种以深度优先的方式系统地搜索问题解的算法为回溯法,它适合与求解解空间较大的问题。(P108)
解决问题的基本步骤:
(1)针对所给问题,定义问题的解空间:子集树问题、排列树问题和其他因素;
(2)确定状态空间树的结构;
(3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。其中深度优先方式可以选择递归回溯或者迭代回溯
贪⼼策略适⽤的前提是:局部最优策略能导致产⽣全局最优解。 从问题的某⼀个初始解出发,逐步逼近给定的⽬标,以便更快的求出更好的解。当达到算法 中某⼀步不能再向前时,就停⽌算法,给出⼀个近似解。贪心算法的思想是通过选择局部最优以求得最优解,用于解决具有最大值或最小值的优化问题。
缺点:
(1)不能保证最后的解是最优解;
(2)不能⽤来求最⼤、最⼩解问题;
(3)只能求满⾜某些约束条件的可⾏解范围。
可以⽤贪⼼算法解决的问题:货币选择问题,区间调度问题,活动安排问题。最小生成树、哈弗曼、单元最短路径。
不能⽤贪⼼算法解决的问题:N 皇后问题,0/1 背包问题,无向图找最短路径问题。
共同点:二者都要求原问题具有最优子结构性质,都是将原问题分而治之,分解成若干个规模较小的子问题.然后将子问题的解合并,形成原问题的解.
分治法与动态规划实现方法:① 分治法通常利用递归求解.② 动态规划通常利用迭代法自底向上求解,但也能用具有记忆功能的递归法自顶向下求解.
分治法与动态规划主要区别:① 分治法将分解后的子问题看成相互独立的.② 动态规划将分解后的子问题理解为相互间有联系,有重叠部分.(分治法是将一个问题划分成一系列独立的子问题,分别处理后将结果组合以得到原问题的答案。动态规划同样将一个问题划分成一系列子问题进行处理,但当子问题不是互相独立而是互有联系时,动态规划不会重复计算子问题间联系的问题,是更高效的解决办法。)
回溯法:先定义问题的解空间,然后在问题的解空间树中,按深度优先策略,从根节点出发搜索解空间树。它其实就是“试探着走”,如果尝试不成功则退回一步,再换一个方法试试,反复进行这种试探性选择与返回纠错过程,直到求出问题的解为止。
分支限界法:将问题分支为子问题并对这些子问题定界的步骤称为分支限界法,它对有约束条件的最优化问题的所有可行解的空间进行搜索。它以广度优先或以最小耗费优先的方式搜索问题的解空间树。
提高算法的效率。问题的复杂过程和规模的线性增长导致时耗的增长和空间需求的增长,对低效的算法来说是超线性的,绝非计算机的速度和容量的线性增长得来的时耗减少和存储空间的扩大所能抵消的。
时间复杂度可以帮助我们优化算法。
⽐如,做数组搜索,在最坏的情况并且 n ⾜够⼤时,有序数组的⼆分搜索(时间复杂度 O(logn)) 会远⽐挨个匹配(时间复杂度 O(n))快。所以我们知道⼀个数组是有序数组时,我们做搜索应 该选择⼆分搜索⽽不是挨个匹配。
定义:
P={L|L是一个能在多项式时间内被一台DTM所接受的语言}
NP={L|L是一个能在多项式时间内被一台NDTM所接受的语言}
证明一问题属于NPC问题的基本步骤如下:
首先证明某一问题π是属于NP类问题
选择一个已知NPC问题的局部π’
证明其局部问题π’是属于问题π的,于是证明了问题π也是NPC类问题
证明⽅法:
1.证明 问题 属于 NP 问题,记为问题A
2.选择某个已知的 NPC 问题,记为问题 B
3.证明 问题A 可以在多项式时间⾥约化为 问题B。
常用三种方法:限制法,局部替换法,分量设计法。