一、题目
给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。
子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。
点击查看原题
难度级别: 中等
二、思路
1)动态规划
设立二维数组dp[i][j]
为s[i,j]
最长的回文子序列,可以得到状态转移方程:
d
p
[
i
]
[
j
]
=
{
d
p
[
i
+
1
]
[
j
−
1
]
+
2
,
s
[
i
]
=
=
s
[
j
]
m
a
x
(
d
p
[
i
]
[
j
−
1
]
,
d
p
[
i
+
1
]
[
j
]
)
,
e
l
s
e
dp[i][j]=\left\{\begin{matrix} dp[i+1][j-1]+2,s[i]==s[j]\\ max(dp[i][j-1],dp[i+1][j]),else \end{matrix}\right.
dp[i][j]={dp[i+1][j−1]+2,s[i]==s[j]max(dp[i][j−1],dp[i+1][j]),else
由于该数组只依赖于本行和商议后状态,也可以优化成一维数组,从后向前遍历字符位置为i
,令dp[j]
为s[i,j]
最长的回文子序列
三、代码
1)动态规划
class Solution {
public int longestPalindromeSubseq(String s) {
char[] cs = s.toCharArray();
int[][] dp = new int[cs.length][cs.length];
for (int i = cs.length - 1; i >= 0; i--) {
dp[i][i] = 1;
for (int j = i + 1; j < cs.length; j++) {
if (cs[i] == cs[j]) {
dp[i][j] = dp[i+1][j-1] + 2;
} else {
dp[i][j] = Math.max(dp[i+1][j], dp[i][j-1]);
}
}
}
return dp[0][cs.length - 1];
}
}
时间复杂度为O(n^2)
,空间复杂度为O(n^2)
class Solution {
public int longestPalindromeSubseq(String s) {
char[] cs = s.toCharArray();
int[] dp = new int[cs.length];
for (int i = cs.length - 1; i >= 0; i--) {
int[] temp = dp;
dp = new int[cs.length];
dp[i] = 1;
for (int j = i + 1; j < cs.length; j++) {
if (cs[i] == cs[j]) {
dp[j] = temp[j-1] + 2;
} else {
dp[j] = Math.max(temp[j], dp[j-1]);
}
}
}
return dp[cs.length - 1];
}
}
时间复杂度为O(n^2)
,空间复杂度为O(n)