代码随想录算法训练营第57天 | 647.回文子串, 516.最长回文子序列, 动态规划总结篇
647.回文子串
题目
根据给定的字符串计算这个字符串里有多少回文子串.
题目分析
动态规划五部曲:
确定dp数组及下标的含义
如果规定dp[i]是以下标i为结尾的字符串有dp[i]个回文串的话, 会发现dp[i], dp[i-1], dp[i+1]之间没有什么关系, 这就不符合动态规划的条件了.
由回文串的性质可知, 如果s[i, j]区间的子串是回文串的话, 那么如果s[i-1]==s[j+1], 则s[i-1. j+1]也一定是回文串, 故可以有dp[i][j]表示s[i, j]之间的字符能够形成回文串与否.
确定递推公式
如果s[i] != s[j], 则dp[i][j]一定是false;
若s[i] == s[j],
- 若i == j, 即同一个字符, 是回文串, dp[i][j] = true;
- 若i != j, 但 j - i = 1, 即相邻字符相等, 则也是回文串, dp[i][j] = true;
- 若i != j, 且 i 与 j相差超过1, 则需要看dp[i+1][j-1]是否为回文串, 即dp[i][j] = dp[i + 1][j - 1];
dp数组的初始化
全部初始化为false.
遍历顺序
由递推公式知, dp[i][j]会由左下角的值推出, 故应当外围for循环从后向前, 内层for循环从前向后.
题解
动态规划:
1 |
|
双指针法:
1 |
|
516.最长回文子序列
题目
从给定的字符串中找出最长的回文子序列, 返回其长度.
题目分析
动态规划五部曲:
确定dp数组及下标的含义
dp[i][j]表示s[i, j]范围内最长的回文子序列的长度为dp[i][j].
确定递推公式
如果s[i] == s[j], 则dp[i][j] = dp[i + 1][j - 1] + 2;
如果s[i] != s[j], 则尝试让s[i] 和 s[j] 分别加入 s[i + 1, j - 1]的序列中, 求回文子序列的最大长度, 即dp[i][j] = max(dp[i][j - 1], dp[i + 1][j]).
dp数组的初始化
二维数组正对角线上的值全部初始化为1, 其余部分为0.
遍历顺序
由递推公式知, dp[i][j]的来源状态有dp[i + 1][j - 1], dp[i][j - 1], dp[i + 1][j]. 故遍历顺序一定是从下往上, 从左向右.
题解
1 |
|
动态规划总结篇
最重要的:
动态规划五部曲:
- 确定dp数组及下标的含义
- 确定递推公式
- dp数组的初始化
- 遍历顺序
- 举例推导
代码随想录算法训练营第57天 | 647.回文子串, 516.最长回文子序列, 动态规划总结篇