动态规划一般也只能应用于有最优子结构的问题。最优子结构的意思是局部最优解能决定全局最优解
(对有些问题这个要求并不能完全满足,故有时需要引入一定的近似)。
简单地说,问题能够分解成子问题来解决。
动态规划算法分以下4个步骤:
1.描述最优解的结构
2.递归定义最优解的值
3.按自底向上的方式计算最优解的值 //此3步构成动态规划解的基础。
4.由计算出的结果构造一个最优解。 //此步如果只要求计算最优解的值时,可省略。
好,接下来,咱们讨论适合采用动态规划方法的最优化问题的俩个要素:
最优子结构性质,和子问题重叠性质。
一、最优子结构。
如果问题的最优解所包含的子问题的解也是最优的,我们就称该问题具有最优子结构性质(即满足最优化原理)。
意思就是,总问题包含很多歌子问题,而这些子问题的解也是最优的。
二、重叠子问题。
子问题重叠性质是指在用递归算法自顶向下对问题进行求解时,每次产生的子问题并不总是新问题,
有些子问题会被重复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只计算一次,
然后将其计算结果保存在一个表格中,当再次需要计算已经计算过的子问题时,只是在表格中简单地查看一下结果,
从而获得较高的效率。
ok,咱们马上进入面试题第56题的求解,即运用经典的动态规划算法:
56.最长公共子序列。
题目:如果字符串一的所有字符按其在字符串中的顺序出现在另外一个字符串二中,
则字符串一称之为字符串二的子串。
注意,并不要求子串(字符串一)的字符必须连续出现在字符串二中。
请编写一个函数,输入两个字符串,求它们的最长公共子串,并打印出最长公共子串。
例如:输入两个字符串BDCABA和ABCBDAB,字符串BCBA和BDAB都是是它们的最长公共子串,
则输出它们的长度4,并打印任意一个子串。
分析:求最长公共子串(Longest Common Subsequence, LCS)是一道非常经典的动态规划题,
因此一些重视算法的公司像MicroStrategy都把它当作面试题。
步骤一、描述一个最长公共子序列
先介绍LCS问题的性质:记Xm={x0, x1,…xm-1}和Yn={y0,y1,…,yn-1}为两个字符串,
并设Zk={z0,z1,…zk-1}是X和Y的任意一个LCS,则可得出3条性质:
1. 如果xm-1=yn-1,那么zk-1=xm-1=yn-1,并且Zk-1是Xm-1和Yn-1的一个LCS;
2. 如果xm-1≠yn-1,那么当zk-1≠xm-1时,Z是Xm-1和Y的LCS;
3. 如果xm-1≠yn-1,那么当zk-1≠yn-1时,Z是X和Yn-1的LCS;
下面简单证明一下由上述相应条件得出的这些性质: