LeetCode 647.回文子串

133 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

题目:给定一个字符串s,请统计并返回这个字符串中回文子串的个数。

解题思路

一个字符串的所有回文子串的个数,那么我们是否可以先获取字符串的所有子串,之后挨个判断是否为回文子串即可,可得代码如下:

public int countSubStrings(String s){
    int count = 0;
    for(int i=0;i<s.length();i++){
        StringBuilder sb = new StringBuilder();
        for(int j=i;j<s.length();j++){
            sb.append(s.charAt(j));
            StringBuilder st = new StringBuilder(sb.toString());
            if(sb.toString().contentEquals(st.reverse())) count++;
        }
    }
    return count;
}

时间复杂度为O(N2)O(N^2),方法是对的,下次别用了,哈哈哈哈。

换个思路,我们直接来看一个回文子串abba,可以看到0索引元素等于3索引,之后我们再看1索引元素等于2索引,经过这两步可判断03的字符串为一个回文串,那么根据这个思路:

我们可以首先双重for循环遍历所有可能的子串,而对于索引i到索引j的子串,首先判断ij位置元素是否相等,不相等则必定不可能是回文串,相等则看ij中间有几个元素,有一个则也是回文串,如果大于一个则再看i+1j-1的子串是否为回文串,依次类推即可。

上述过程显然可以用动态规划解决,因为在计算dp[i][j](指由ij组成的字符串)时,dp[i+1][j-1]必然已经计算完毕了,而要保证这点,则for循环的外层循环控制的是结束点,也即j,内层控制的是i,可得代码如下:

public int countSubStrings2(String s){
    int count = 0, len = s.length();
    boolean[][] dp = new boolean[len][len];
    for(int i=0;i<len;i++){
        for(int j=0;j<=i;j++){
            if(s.charAt(i) == s.charAt(j)){
                if(i-j<3){
                    dp[j][i] = true;
                }else {
                    dp[j][i] = dp[j+1][i-1];
                }
            }else {
                dp[j][i] = false;
            }
        }
    }
    for(int i=0;i<len;i++) {
        for (int j = 0; j < len; j++) {
            if (dp[i][j]){count++;
            System.out.println(i+""+j);}
        }
    }
    return count;
}

该方法时间复杂度为O(N2)O(N^2)。看了题解,发现还有一种比较巧妙的思路,中心扩散法。

该方法首先判断所有可能的回文中心点,对于一个长度为n的字符串,其回文中心点有2*n-1个,其中单字符回文中心n个,双字符回文中心n-1个,这比较容易理解。但回文中心的左边界和右边界不好确定,由分析可知,单字符回文中心左边界为0,右边界也为0。而双字符的回文中心点其右边界应该是1。由这一规律,可知左边界索引为i/2下取整,右边界则i/2 + i%2。最终可得代码:

public int countSubStrings3(String s){
    int count = 0;
    for(int i=0;i<2*s.length()-1;i++){
        int left = i/2;
        int right = left + i%2;
        while(left>=0&&right<s.length()&&s.charAt(left)==s.charAt(right)){
            left--;
            right++;
            count++;
        }
    }
    return count;
}

时间复杂度也是O(n2)O(n^2)