1. 程式人生 > >#leetcode#647. Palindromic Substrings

#leetcode#647. Palindromic Substrings

https://leetcode.com/problems/palindromic-substrings/description/

Given a string, your task is to count how many palindromic substrings in this string.

The substrings with different start indexes or end indexes are counted as different substrings even they consist of same characters.

Example 1:

Input:
"abc" Output: 3 Explanation: Three palindromic strings: "a", "b", "c".

Example 2:

Input: "aaa"
Output: 6
Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa".

Note:

  1. The input string length won't exceed 1000.

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Palindrome無非兩種做法, 1, two pointers,以每個character為中心或者以兩個character之間的位置為中心向左右兩邊擴散, 找回文。 2, 用dp,套路理解完之後就是怎麼套入不同的問題,比如這個,不讓你找最長迴文子串,而是找不同迴文的個數,那麼dp解法中只要當dp[i][j] == true 時, count++即可,two pointers做法就有點變化了。

之前看code ganker大神的two pointers做法,是這麼找中心起點的:

for(int i = 0; i < 2 * s.length() - 1; i++){
    int left = i / 2;
    int right = i / 2;
    if(i % 2 == 1){
        right++;
    }
}

其實有點繁瑣, 與其理解為找中心, 不如理解為如何初始化左指標與右指標,以character為中心, 則 left == right == index. 以兩個character中間位置為中心, 則left == index, right == index + 1;

two pointers 解法:

class Solution {
    public int countSubstrings(String s) {
        if(s == null || s.length() == 0)
            return 0;
        int res = 0;
        for(int i = 0; i < s.length(); i++){
            res += count(s, i, i);
            res += count(s, i, i + 1);
        }
        return res;
    }
    
    private int count(String s, int l, int r){
        int res = 0;
        while(l >= 0 && r < s.length() && s.charAt(l--) == s.charAt(r++)){
            res++;
        }
        return res;
    }
}

dp解法:

class Solution {
    public int countSubstrings(String s) {
        if(s == null || s.length() == 0)
            return 0;
        int len = s.length();
        int res = 0;
        boolean[][] dp = new boolean[len][len];
        for(int i = len - 1; i >= 0; i--){
            for(int j = i; j < len; j++){
                if(s.charAt(i) == s.charAt(j) && (j - i <= 2 || dp[i + 1][j - 1])){
                    dp[i][j] = true;
                    res++;
                }
            }
        }
        
        return res;
    }
}

這裡two pointers解法是優於dp的, 因為dp需要O(n^2) space, two pointers只要O(1) space, 而時間複雜度都是O(n^2)