回文子串
链接: 647. 回文子串
思路
重点区分回文子串与回文子序列的长度,
子串说明这个子字符串必须是连续的
而回文子序列不一定连续。
动态规划
本题因为回文子串是连续的字符串,不能用一般的动态规划方法做
(maybe)
1.dp数组含义
dp[i][j]
表示下标i到下标j构成子串是回文串
2.递推公式
宏观把握:该回文串依赖dp[i + 1][j - 1]
是否为true
细化,如果i 和 j 相同 或者相差一个元素,i + 1和j - 1这种形式正好错开,我们距离发现,当s.charAt(i) =s.charAt(j),即使不关注dp[i + 1][j - 1]
,dp[i][j]
依然是回文子串
所以就可以分为三种(or前两种合并)情况。
3.初始化
默认初始值都为false
4.遍历顺序
这个最好在草稿纸上写一写,由递推公式看出是从左到右,从下到上,所以i 我们采用倒序方法。
双指针法
双指针法是一种,我很难想到的方法,思路很简单,但实现起来感觉很绕。
首先确定回文串,就是找中心然后向两边扩散看是不是对称的就可以了
在遍历中心点的时候,要注意中心点有两种情况:
一个元素可以作为中心点,两个元素也可以作为中心点
(需要多注意)
代码
// 动态规划
class Solution {
public int countSubstrings(String s) {
int len = s.length();
int result = 0;
// dp[i][j]表示下标i到下标j构成子串是回文串
// 该回文串依赖dp[i + 1][j - 1]是否为true
boolean[][] dp = new boolean[len][len];
for (int i = len - 1;i >= 0;i--){
for (int j = i;j < len;j++){
if (s.charAt(i) == s.charAt(j)){
if (j - i <= 1){
result++;
dp[i][j] = true;
}else if (dp[i + 1][j - 1]){
result++;
dp[i][j] = true;
}
}
}
}
return result;
}
}
// 双指针法
class Solution {
public int countSubstrings(String s) {
int result = 0;
for (int i = 0; i < s.length(); i++) {
result += extend(s, i, i, s.length()); // 以i为中心
result += extend(s, i, i + 1, s.length()); // 以i和i+1为中心
}
return result;
}
int extend(String s, int i, int j, int n) {
int res = 0;
while (i >= 0 && j < n && s.charAt(i) == s.charAt(j)) {
i--;
j++;
res++;
}
return res;
}
}
最长回文子序列
链接: 516.最长回文子序列
思路
动态规划五部曲:
1.dp数组含义
dp[i][j]
:字符串s在[i, j]范围内最长的回文子序列的长度为dp[i][j]
。
2.递推公式
如果s.charAt(i) == s.charAt(j),则dp[i][j] = dp[i + 1][j - 1] + 2
如果不等,规则和一般的子序列匹配差不多
dp[i][j] = Math.max(dp[i + 1][j],dp[i][j - 1]);
3.初始化
和一般的初始化不同,本题是求回文,单独一个字符也是回文,所以二维数组斜对角线元素初始化为1
4.遍历顺序
由递推公式可知,从左到右,从下到上
5.举例推导:略
代码
class Solution {
public int longestPalindromeSubseq(String s) {
int len = s.length();
int[][] dp = new int[len][len];
for (int i = 0;i < len;i++){
dp[i][i] = 1;
}
for (int i = len - 1;i >= 0;i--){
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],dp[i][j - 1]);
}
}
}
// 注意dp数组的含义
return dp[0][len - 1];
}
}