跟着carl学算法,本系列博客仅做个人记录,建议大家都去看carl本人的博客,写的真的很好的!
代码随想录
LeetCode:516.最长回文子序列
给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。
子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。
示例 1:
输入:s = “bbbab”
输出:4
解释:一个可能的最长回文子序列为 “bbbb” 。
示例 2:
输入:s = “cbbd”
输出:2
解释:一个可能的最长回文子序列为 “bb” 。
- 类似上一题
dp[i][j]
表示字符串s
在[i, j]
范围内最长的回文子序列的长度为dp[i][j]
- 初始化:和上一题一样,在
s.charAt(i) == s.charAt(j)
相等时分开考虑:i, j
重合,相差1
,相差大于1
,则不需要初始化 - 递推公式:当
i, j
相等时:如果i,j
重合则dp[i][j] = 1
;如果i,j
相差1
则dp[i][j] = 2
;如果i,j
相差大于1
则dp[i][j] = dp[i + 1][j - 1] + 2
;当i, j
不相等时:dp[i][j] = Math.max(dp[i][j - 1], dp[i + 1][j])
- 遍历顺序:外层
for
循环倒序,内存for
循环正序
java"> public int longestPalindromeSubseq(String s) {int[][] dp = new int[s.length()][s.length()];for (int i = s.length() - 1; i >= 0; i--) {for (int j = i; j < s.length(); j++) {if (s.charAt(i) == s.charAt(j)) {if (j - i == 0) {dp[i][j] = 1;} else if (j - i == 1) {dp[i][j] = 2;} else {dp[i][j] = dp[i + 1][j - 1] + 2;}} else {dp[i][j] = Math.max(dp[i][j - 1], dp[i + 1][j]);}}}return dp[0][s.length() - 1];}
另一种写法,i, j
相等时不分开考虑重合,相差1
,或者大于1
:
java"> public int longestPalindromeSubseq(String s) {int len = s.length();int[][] dp = new int[len + 1][len + 1];for (int i = len - 1; i >= 0; i--) {dp[i][i] = 1; // 初始化for (int j = i + 1; j < len; j++) {if (s.charAt(i) == s.charAt(j)) {dp[i][j] = dp[i + 1][j - 1] + 2;} else {dp[i][j] = Math.max(dp[i + 1][j], Math.max(dp[i][j], dp[i][j - 1]));}}}return dp[0][len - 1];}