2022-10-15 【我的刷题日记】647 回文子串

思路:本题可以使用双指针法和动态规划进行计算,因为之前都是动态规划的题目,所以这题也先用动态规划来解决,一开始看到题目会想到把dp数组设置为一维的,直接代表长度为i的字符串个数,但是会发现这种做法是没法进行推导dp数组的,因为回文字符串的判断值通过一个方向是无法做到的,所以dp数组还是得设置为二维的,同时判断回文字符串的时候没法直接从上一个状态累加个数,所以改用计数器来记录个数,dp数组用于判断是否是回文字符串,那么我们用布尔数组而不是int数组来表示dp,dp[i][j]表示s[i]到s[j]的字符串是否是回文字符串。
那么在遍历的时候如果s[i]和s[j]不相等 那么s[i]到s[j]一定不是回文字符串,dp[i][j]为false。
而在相等的时候,又要分为三种情况
i==j时 两个指针都指向本身,那么肯定是回文字符串
i和j相邻时 类似与aa bb这种情况,也是回文字符串
i和j不相邻时 类似afqwfba这种情况 只有在fqwfb是回文的时候整体才是回文,所以这时需要判断dp[i+1][j-1]是否为真
那么因为我们在遍历中需要用到dp[i+1][j-1]的值,我们在遍历的时候 i应该从大向小遍历 j从小到大遍历 这样得到的dp[i+1][j-1]的值才是准确的经过计算的

class Solution {
    public int countSubstrings(String s) {
//        dp[i][j]表示[i,j]区间的字符串是否是回文字符串
        boolean[][] dp = new boolean[s.length()][s.length()];
        int res = 0;
        for (int i = s.length() - 1; 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]) {
//                        需要用到dp[i+1][j-1] 所以遍历顺序要以此为基础
                        res++;
                        dp[i][j] = true;
                    }
                }
            }
        }
        return res;
    }
}

你可能感兴趣的:(2022-10-15 【我的刷题日记】647 回文子串)