一、题目
给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。
子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。
示例 1:
输入:s = "bbbab" 输出:4 解释:一个可能的最长回文子序列为 "bbbb" 。
示例 2:
输入:s = "cbbd" 输出:2 解释:一个可能的最长回文子序列为 "bb" 。
提示:
1 <= s.length <= 1000
s
仅由小写英文字母组成
二、代码
class Solution {
public int longestPalindromeSubseq(String s) {
// 判空
if (s == null || s.length() == 0) {
return 0;
}
// 将字符串转换为字符数组
char[] str = s.toCharArray();
// 创建dp数组
int n = str.length;
int[][] dp = new int [n][n];
// 赋初值,对两个对角线赋初值
dp[n - 1][n - 1] = 1;
for (int i = 0; i < n - 1; i++) {
dp[i][i] = 1;
dp[i][i + 1] = str[i] == str[i + 1] ? 2 : 1;
}
// 按照动态转移方程对dp数组进行复制,沿对角线方向进行复制
for (int i = 2; i < n; i++) {
// 之所以这里用j表示列,是因为列的范围更好控制,因为所有的对角线最后一个节点一定都是最后一列,是固定不变的
for (int j = i; j < n; j++) {
int r = j;
int l = r - i;
// 动态转移方程
dp[l][r] = Math.max(dp[l + 1][r], dp[l][r - 1]);
if (str[l] == str[r]) {
dp[l][r] = Math.max(dp[l][r], dp[l + 1][r - 1] + 2);
}
}
}
// 返回结果
return dp[0][n - 1];
}
}
三、解题思路
利用动态规划的思路进行解题。利用已经得出的初值来逐渐退出全部可能的结果。