题目1: 回文子串
- 题目链接:647. 回文子串
1- 思路
动规五部曲
- 1. 确定 dp 数组含义
dp[i][j]
代表[i,j]
区间内的子串是否是回文串
- 2. 确定递推公式
- 如果两边相同
if(s.charAat(i) == s.charAt(j))
有三种情况 if(i==j)
此时是回文子串if(i-j == 1)
此时相邻,也是回文串if(i-j > 1)
此时要看 [i+1,j-1] 是不是回文子串
- 如果两边相同
if(s.charAat(i) == s.charAt(j)){
if(i-j <= 1){
dp[i][j] = true;
}else if(dp[i+1][j-1]== true){
dp[i][j] = true;
res++;
}
}
- 3. dp 数组初始化
- dp 数组初始化为 false
- 4. 遍历顺序(因为dp[i][j] 通过左下角来,因此遍历从左下角开始)
- 从底往上、从左往右遍历
for(int i = s.length();i>=0;i--){
for(int j = i ; j < s.length();j++){
if(s.charAat(i) == s.charAt(j)){
if(i-j <= 1){
res++;
dp[i][j] = true;
}else if(dp[i+1][j-1]== true){
res++;
dp[i][j] = true;
}
}
}
}
- 5. 推导dp 数组
2- 题解
⭐ 回文子串——题解思路
class Solution {
public int countSubstrings(String s) {
// 1. 定义 dp 数组
boolean[][] dp = new boolean[s.length()][s.length()];
int res = 0;
// 2. 递推公式
// if(s.charAt(i) == s.charAt(j)){
// if(j-i<=1){
// dp[i][j] = true;
// }else if (dp[i+1][j-1]==true){
// dp[i+1][j-1] = true;
// res++;
// }
// }
// 3. 初始化 都为 false
// 4. 变量顺序,从下到上、从左到右
for(int i = s.length();i>=0;i--){
for(int j = i;j<s.length();j++){
if(s.charAt(i) == s.charAt(j)){
if(j-i<=1){
res++;
dp[i][j] = true;
}else if (dp[i+1][j-1]){
res++;
dp[i][j] = true;
}
}
}
}
return res;
}
}
题目2: 最长回文子序列
- 题目链接:516. 最长回文子序列
1- 思路
注意:本题区别于回文子串的区别在于,本题可以不连续
动规五部曲
- 1. 确定 dp 数组含义
dp[i][j]
代表[i,j]
区间内的最长回文子串的长度
- 2. 确定递推公式
- 若相等:
if(s.charAt(i) == s.charAt(j))
此时代表,两边相等dp[i][j] = dp[i+1][j-1]+2
- 若不相等 else
- 考虑 i 不考虑 j,
dp[i][j] = dp[i][j-1]
- 考虑 j 不考虑 i,
dp[i][j] = dp[i+1][j]
- 考虑 i 不考虑 j,
- 结论
dp[i][j] = Math.max(dp[i][j-1],dp[i+1][j])
- 若相等:
- 3. dp 数组初始化
- 在
i==j
的时候需要对数组进行初始化,回文长度为 1,dp[i][i]=1
- 在
- 4. 遍历顺序(因为dp[i][j] 通过左下角来,因此遍历从左下角开始)
- 从底往上、从左往右遍历
for(int i = s.length();i>=0;i--){
for(int j = i+1 ; j < s.length();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][j-1],dp[i+1][j])
}
}
}
- 5.推导 dp 数组
2- 题解
⭐ 最长回文子序列——题解思路
class Solution {
public int longestPalindromeSubseq(String s) {
// 1. 定义dp数组
int[][] dp = new int[s.length()][s.length()];
// 2. 递推公式
// 相等 dp[i][j] = dp[i+1][j-1]+2
// 不等 dp[i][j] = Math.max(dp[i+1][j],dp[i][j-1]);
// 3. 初始化
for(int i = 0 ; i < s.length();i++){
dp[i][i] = 1;
}
// 4. 遍历
for(int i = s.length();i>=0;i--){
for(int j = i+1; j<s.length();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][j],Math.max(dp[i+1][j],dp[i][j-1]));
}
}
}
return dp[0][s.length()-1];
}
}