LC.P516[最长回文子序列]
题目描述
给你一个字符串 s
,找出其中最长的回文子序列,并返回该序列的长度。
子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。
示例 1:
输入:s = “bbbab”
输出:4
解释:一个可能的最长回文子序列为 “bbbb” 。
示例 2:
输入:s = “cbbd”
输出:2
解释:一个可能的最长回文子序列为 “bb” 。
提示:
1 <= s.length <= 1000
s
仅由小写英文字母组成
方法一:区间DP+记忆化搜索
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class Solution { String s; int[][] cache;
public int longestPalindromeSubseq(String s) { this.s = s; int n = s.length(); cache = new int[n][n]; return dfs(0, n - 1); }
private int dfs(int i, int j) { if (i > j) return 0; if (i == j) return 1; if (cache[i][j] != 0) return cache[i][j]; if (s.charAt(i) == s.charAt(j)) { cache[i][j] = dfs(i + 1, j - 1) + 2; return cache[i][j]; } cache[i][j] = Math.max(dfs(i + 1, j), dfs(i, j - 1)); return cache[i][j]; } }
|
- 时间复杂度:$O(n^2)$
- 空间复杂度:$O(n^2)$
方法二:1:1翻译成递推
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Solution { public int longestPalindromeSubseq(String S) { char[] s = S.toCharArray(); int n = s.length; int[][] f = new int[n][n]; for (int i = n - 1; i >= 0; --i) { f[i][i] = 1; for (int j = i + 1; j < n; ++j) { if (s[i] == s[j]) f[i][j] = f[i + 1][j - 1] + 2; else f[i][j] = Math.max(f[i + 1][j], f[i][j - 1]); } } return f[0][n - 1]; } }
|
- 时间复杂度:$O(n^2)$
- 空间复杂度:$O(n^2)$