动态规划(一)
动态规划
Those who do not remember the past are condemned to repeat it.
理论
- 特点
- 重复子问题:需要记录之前的计算结果;
- 最优子结构:不同规模之间的关系;
- 后无效性:只记录阶段结果而不关心这个结果是怎么来的;
- 思路方向
- 自顶向下:递归+记忆化;
- 自底向上:递推求解。
- 状态转移方程
- 将当前问题分解为几个小问题,这些小问题的最优解构成当前问题的最优解;
- 初始化
- 输出
- 有时题目的解并不是最后一个状态
- 考虑是否有可优化空间
例题
最长回文子串
题目:
给你一个字符串 s,找到 s 中最长的回文子串。
1 | 示例 1: |
1 | 示例 2: |
解题思路:
状态转移方程
- 对于一个长度大于2的子串而言,如果他是回文串,那么它的首尾字符相同且去掉首尾两个字符,它任然是个回文串。
- 使用f(i, j)表示字符串s从第i个字符到第j个字符所组成的字符串 ,f(i, j)是回文串等价 于 f(i + 1, j - 1)是回文串且s[i] 和 s[j]相等。 根据这样的思路可以得出他的状态转移方程:
1
f(i,j) = f(i + 1, j - 1) ∧ (s[i]== s[j])
初始化
- 对于长度大于3的状态可以使用状态转移方程,对于长度为1的字符串,它肯定是一个回文串;对于长度为2的字符串,当两个字符相同即s[i] = s[i+1]时,它是一个回文串,所以可得出初始化:
1
2
3f(i, i) = true
f(i, i+1) = (s[i] == s[i + 1])
思考输出
- 我们需要求出的结果是最长回文串,是整个计算过程中的某一个状态,并不一定是是递归到最后一层所得出的结果。
- 设置maxLength = 0, 每当计算出一个状态且子串长度大于maxLength时更新maxLength的值并记录子串。
代码
1 | public String longestPalindrome(String s) { |
复杂度分析:二维 dp 问题,一个状态得用二维有序数对表示。
1 | 时间复杂度:O(N^{2}) |
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.