647. 回文子串(Java)(中心扩展,思维)(动归乱序迭代)

1 题目

给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。

具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被计为是不同的子串。

示例 1:

输入: “abc”
输出: 3
解释: 三个回文子串: “a”, “b”, “c”.
示例 2:

输入: “aaa”
输出: 6
说明: 6个回文子串: “a”, “a”, “a”, “aa”, “aa”, “aaa”.
注意:

输入的字符串长度不会超过1000。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindromic-substrings
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2 Java

2.1 !方法一(中心扩展,思维)

遍历每个 / 每两个字符,作为回文字符串的中心
不断扩展回文字符串,并记录回文字符串数量

class Solution {
    public int countSubstrings(String s) {
        int ans = 0, N = s.length();

        // “abc”的中心位置可以是a,也可以是ab,所以存在两个字符的中心
        // l和r为中心的范围,i是为了应对两字符中心的情况
        for(int i = 0; i <= 2 * N - 2; i++){
            int l = i / 2, r = l + i % 2;
            while(l >= 0 && r < N && s.charAt(l) == s.charAt(r)){
                l--;    r++;
                ans++;
            }
        }

        return ans;
    }
}

2.2 !!!方法二(动归乱序迭代)

dp[i][j]:代表[i, j]是否为回文字符串
状态转移方程:回文字符串两段加同样字符,仍为回文字符串
向前步进:一定注意for步进的方向,与状态转移方程有关,必须由之前的dp得到之后的dp!!!
本题dp[i][j]由dp[i + 1][j - 1]得到,所以i在步进,j在步退

class Solution {
    public int countSubstrings(String s) {
        int ans = 0, N = s.length();
        // 创建备忘录;代表[i, j]是否为回文字符串
        boolean[][] dp = new boolean[N][N];

        // 状态转移方程;回文字符串两段加同样字符,仍为回文字符串
        // 向前步进;一定注意for步进的顺序,与状态转移方程有关,必须由之前的dp得到之后的dp!!!
        for(int j = 0; j < N; j++){
            for(int i = j; i >= 0; i--){
                if(s.charAt(i) == s.charAt(j) && (j - i <= 1 || dp[i + 1][j - 1])){
                    dp[i][j] = true;
                    ans++;
                }
            }
        }

        return ans;
    }
}

经典错误,两个for循环的步进与状态转移方程不匹配

class Solution {
    public int countSubstrings(String s) {
        int ans = 0, N = s.length();
        // 创建备忘录;代表[i, j]是否为回文字符串
        boolean[][] dp = new boolean[N][N];

        // 状态转移方程:回文字符串两段加同样字符,仍为回文字符串
        // 向前步进;一定注意for步进的顺序,与状态转移方程有关,必须由之前的dp得到之后的dp!!!
        // !!!经典错误,两个for循环的步进与状态转移方程不匹配
        for(int i = 0; i < N; i++){
            for(int j = i; j < N; j++){
                if(s.charAt(i) == s.charAt(j) && (j - i <= 1 || dp[i + 1][j - 1])){
                    dp[i][j] = true;
                    ans++;
                }
            }
        }

        return ans;
    }
}
发布了131 篇原创文章 · 获赞 0 · 访问量 2263

猜你喜欢

转载自blog.csdn.net/weixin_43969686/article/details/105326305