> 文章列表 > 代码随想录打卡第57天|647. 回文子串;516.最长回文子序列

代码随想录打卡第57天|647. 回文子串;516.最长回文子序列

代码随想录打卡第57天|647. 回文子串;516.最长回文子序列

647. 回文子串

关键点1:dp数组的含义

dp[i][j]:s字符串下标i到下标j的子串是否是一个回文串,即s[i, j]

关键点2:递归公式的推导

if(s.charAt(i) == s.charAt(j))有两种情况

情况1:j-i<=1; j=i代表一个字母,是回文子串,j-i=1代表i,j相邻且相等,是回文子串,所以返回true

情况2:j-i >1;i和j同时向里移动,所以为i+1,j-1;dp[i][j] = dp[i+1][j-1];

if(s.charAt(i) != s.charAt(j)),如果不相等:则返回false,因为初始化dp数组为false,所以这条为默认情况,可以不写

关键点3:dp数组初始化

dp数组全部初始化为false

关键点4:遍历顺序

由于dp[i][j] = dp[i+1][j-1];
所以下一个dp值与它左下方的dp值有关,因此for循环从下往上遍历(i)从左到右遍历;j从i开始,因为j>=i

class Solution {public int countSubstrings(String s) {int len = s.length();int res = 0;//dp[i][j]:s字符串下标i到下标j的子串是否是一个回文串,即s[i, j]boolean[][] dp = new boolean[len][len];// 初始化,都为falsefor(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){dp[i][j] = true;}else{dp[i][j] = dp[i+1][j-1];}}if(dp[i][j]){res++;}}}return res;}
}

516.最长回文子序列

关键点1:dp数组的含义

dp[i][j]:从下标i到下标j的子串的最长回文子序列的长度

关键点2:递归公式的推导

if(s.charAt(i) == s.charAt(j)),dp[i][j] = dp[i+1][j-1]+2;

if(s.charAt(i) != s.charAt(j)),如果不相等,则有两种情况:

情况1:dp[i][j-1],j往里走一个

情况2:dp[i+1][j],i往里走一个

情况1与情况2求一个最大值

关键点3:dp数组初始化

i,j往里走到最中间的位置,为同一个元素,则回文子序列的长度为1;所以dp[i][i] = 1;

关键点4:遍历顺序

由于dp[i][j] = dp[i+1][j-1];
所以下一个dp值与它左下方的dp值有关,因此for循环从下往上遍历(i)从左到右遍历;j从i+1开始,因为j>=i,j=i的情况已经初始化了,所以j >i

class Solution {public int longestPalindromeSubseq(String s) {//dp[i][j]:从下标i到下标j的子串的最长回文子序列的长度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][j-1],dp[i+1][j]); }}}return dp[0][len-1];}
}