LeetCode 647. 回文子串(动态规划)

647. 回文子串

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

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

示例 1:

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

输入:“aaa”
输出:6
解释:6个回文子串: “a”, “a”, “a”, “aa”, “aa”, “aaa”

提示:

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

方法一

动态规划。dp[i][j]表示[i, j)区间内的字符串是否是回文串. 时间复杂度O(n^2),空间复杂度O(n^2).

代码

class Solution {
    public int countSubstrings(String s) {
        int n = s.length();
        boolean[][] dp = new boolean[n+1][n+1];
        for (int i=0; i<n; ++i) {
            dp[i][i] = dp[i][i+1] = true;
        }
        int cnt = n;
        for (int w=2; w<=n; ++w) {
            for (int i=0; i<=n-w; ++i) {
                if (s.charAt(i) == s.charAt(i+w-1)) {
                    dp[i][i+w] = dp[i+1][i+w-1];
                    if (dp[i][i+w]) {
                        ++cnt;
                    }
                }
            }
        }
        return cnt;
    }
}

方法二

遍历字符串的每个字符,以此为中心向两边扩展判断是否回文,分回文子串的长度是奇数还是偶数进行讨论。时间复杂度O(n^2),空间复杂度O(1).

代码

class Solution {
public:
    int countSubstrings(string s) {
        int n = s.size(), cntOdd = n, cntEven = 0;
        for (int i=0; i<n; ++i) {
            for (int j=1; j<=std::min(i, n-1-i); ++j) {
                if (s[i-j] == s[i+j]) {
                    ++cntOdd;
                } else {
                    break;
                }
            }
            for (int j=0; j<=std::min(i, n-2-i); ++j) {
                if (s[i-j] == s[i+j+1]) {
                    ++cntEven;
                } else {
                    break;
                }
            }
        }
        return cntOdd + cntEven;
    }
};

你可能感兴趣的:(LeetCode,LeetCode,动态规划,回文子串)