代码随想录刷题记录 day49 回文子串+最长回文子串

代码随想录刷题记录 day49 回文子串+最长回文子串

647. 回文子串

代码随想录刷题记录 day49 回文子串+最长回文子串_第1张图片

思想

方法1:

暴力解 两层for 去判断是否是回文子串,双指针。

方法2:

动态规划

1.dp数组的定义
dp[i][j] 表示字符串 区间[i,j] 是否是回文子串  如果是则为true  不是则为false

2.递推公式
2.1 s[i]!=s[j] dp[i][j]=false;
2.2 s[i]==s[j] 
2.2.1 同一个字符 比如a 是回文子串
2.2.2 相差一个  aa 也是回文子串
2.2.3 相差大于1  看dp[i+1][j-1]是否是回文 比如 cabac  看aba是否是回文
        
3.初始化
初始化为false 还没有匹配的时候都是false

4.遍历顺序
dp[i][j]依赖于dp[i+1][j-1] 所以遍历顺序是从下到上 从左到右

5.数组的打印

代码随想录刷题记录 day49 回文子串+最长回文子串_第2张图片

代码
class Solution {
    // public int countSubstrings(String s) {
    //     int count=0;
    //     for(int i=0;i
    //         for(int j=i;j
    //             if(isValid(s,i,j)) count++;
    //         }
    //     }
    //     return count;
    // }

    // public boolean isValid(String s,int left,int right){
    //     //判断字符串s[left,right]是不是回文子穿
    //     while(left
    //         if(s.charAt(left)!=s.charAt(right)){
    //             return false;
    //         }
    //         else{
    //             left++;
    //             right--;
    //         }
    //     }

    //     return true;
    // }

    public int countSubstrings(String s){
        //动态规划方法

        //1.dp数组的定义
        //dp[i][j] 表示字符串 区间[i,j] 是否是回文子串  如果是则为true  不是则为false

        //2。递推公式
        //2.1 s[i]!=s[j] dp[i][j]=false;
        //2.2 s[i]==s[j] 
        //2.2.1 同一个字符 比如a 是回文子串
        //2.2.2 相差一个  aa 也是回文子串
        //2.2.3 相差大于1  看dp[i+1][j-1]是否是回文 比如 cabac  看aba是否是回文
        
        //3.初始化
        
        boolean[][] dp=new boolean[s.length()][s.length()];
        int count=0;

        //4.遍历顺序
        //dp[i][j]依赖于dp[i+1][j-1] 所以遍历顺序是从下到上 从左到右
        for(int i=s.length()-1;i>=0;i--){
            for(int j=i;j<s.length();j++){//由于dp数组的定义,所以j是从i开始的 dp数组只填充右上角
                if(s.charAt(i)!=s.charAt(j)) dp[i][j]=false;
                else{
                    if(j-i<=1) {
                    dp[i][j]=true;
                    count++;
                    }
                    else if(dp[i+1][j-1]){
                        dp[i][j]=true;
                        count++;
                    }
            
                }
            }
        }
        return count;
    }
}

516. 最长回文子序列

代码随想录刷题记录 day49 回文子串+最长回文子串_第3张图片

思想

1.dp数组的定义

dp[i][j] 表示字符串 区间[i,j]的最长回文子串是dp[i][j]

2.递推公式

2.1 s[i]==s[j] dp[i][j]=dp[i+1][j-1]+2;
2.2 s[i]!=s[j] dp[i][j]=Math.max(dp[i+1][j],dp[i][j-1]);

3.初始化

递推公式计算不到 i和j是相同的情况,表示是一个字符串 所以需要手动初始化1

4.遍历顺序

dp[i][j] 依赖于 dp[i+1][j-1] dp[i+1][j] dp[i][j-1] 左边 左下边 和下方

5.数组打印

代码随想录刷题记录 day49 回文子串+最长回文子串_第4张图片

代码
class Solution {
    public int longestPalindromeSubseq(String s) {
        //1.dp数组的定义
        //dp[i][j] 表示字符串 区间[i,j]的最长回文子串是dp[i][j]

        //2.递推公式
        //2.1 s[i]==s[j] dp[i][j]=dp[i+1][j-1]+2;
        //2.2 s[i]!=s[j] dp[i][j]=Math.max(dp[i+1][j],dp[i][j-1]); 

        //3.初始化
        int[][] dp=new int[s.length()][s.length()];
        //递推公式计算不到 i和j是相同的情况,表示是一个字符串 所以需要手动初始化
        for(int i=0;i<s.length();i++){
            dp[i][i]=1;
        }
        
        //4.遍历顺序
        //dp[i][j] 依赖于 dp[i+1][j-1] dp[i+1][j]  dp[i][j-1] 左边 左下边 喝下方
        //所以遍历顺序是从下到上 从左到右
        for(int i=s.length()-1;i>=0;i--){
            for(int j=i+1;j<s.length();j++){//不能是j=i;因为此时相当于是一个字符,dp[i][j]=1 不等于2
                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]); 
                }
            }
        }
        return dp[0][s.length()-1];

    }
}

参考:代码随想录

你可能感兴趣的:(代码随想录刷题记录,leetcode,算法,动态规划)