647.回文子串
思路:印象中要用双指针解决这道题,动态规划实在想不到
答案
class Solution {
public int countSubstrings(String s) {
char[] chars = s.toCharArray();
int len = chars.length;
boolean[][] dp = new boolean[len][len];
int result = 0;
for (int i = len - 1; i >= 0; i--) {
for (int j = i; j < len; j++) {
if (chars[i] == chars[j]) {
if (j - i <= 1) { // 情况一 和 情况二
result++;
dp[i][j] = true;
} else if (dp[i + 1][j - 1]) { //情况三
result++;
dp[i][j] = true;
}
}
}
}
return result;
}
}
小结
dp数组定义:布尔类型的dp[i][j]:表示区间范围[i,j] (注意是左闭右闭)的子串是否是回文子串,如果是dp[i][j]为true,否则为false。
516.最长回文子序列
题目:516. 最长回文子序列 - 力扣(LeetCode)
思路:
dp数组定义:dp[i][j] 表示区间范围[i, j]的子串中最长回文子序列的长度
尝试(部分AC)
class Solution {
public int longestPalindromeSubseq(String s) {
char[] chars = s.toCharArray();
int len = chars.length;
int[][] dp = new int[len][len];
for(int i = len-1; i>=0; i--){
for(int j = i; j<len; j++){
if(chars[i]==chars[j]){
if(j-i>=1){
dp[i][j] = dp[i+1][j-1] + 2;
}
// else if(i==j){
// dp[i][j] = dp[i+1][j-1] + 1;
// }
}else{
dp[i][j] = Math.max(dp[i+1][j],dp[i][j-1]);
}
}
}
return dp[0][len-1];
}
}
// 按照答案,加上dp[i][i] = 1的初始化就行了
class Solution {
public int longestPalindromeSubseq(String s) {
char[] chars = s.toCharArray();
int len = chars.length;
int[][] dp = new int[len][len];
for(int i = len-1; i>=0; i--){
dp[i][i] = 1;
for(int j = i+1; j<len; j++){
if(chars[i]==chars[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][len-1];
}
}
答案
public class Solution {
public int longestPalindromeSubseq(String s) {
int len = s.length();
int[][] dp = new int[len + 1][len + 1];
for (int i = len - 1; i >= 0; i--) { // 从后往前遍历 保证情况不漏
dp[i][i] = 1; // 初始化
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], Math.max(dp[i][j], dp[i][j - 1]));
}
}
}
return dp[0][len - 1];
}
}
小结
初始化没想到,要初始化对角线上的dp[i][i],因为单独一个字母就是回文的