1. 程式人生 > 其它 >力扣647(迴文子串)

力扣647(迴文子串)

647.迴文子串

基本思想:

動態規劃

具體實現:

1.確定dp陣列(dp table)以及下標的含義

布林型別的dp[i][j]:表示區間範圍[i,j] (注意是左閉右閉)的子串是否是迴文子串,

如果是dp[i][j]為true,否則為false。

2.確定遞推公式

(1)s[i]!=s[j],dp[i][j]=false

(2)s[i]=s[j]

  (情況1)下標i 與 j相同,同一個字元例如a,是迴文子串

  (情況2)下標i 與 j相差為1,例如aa,是迴文子串

  (情況3)下標i 與 j相差大於1的時候

      例如cabac,此時s[i]與s[j]已經相同了,看i到j區間是不是迴文子串就看aba是不是迴文就可以了,

      那麼aba的區間就是 i+1 與 j-1區間,這個區間是不是迴文就看dp[i + 1][j - 1]是否為true。

3.dp陣列如何初始化

·dp[i][j]初始化為false

4.確定遍歷順序

從遞推公式中可以看出,情況3是根據dp[i + 1][j - 1]是否為true,再對dp[i][j]進行賦值true的。

dp[i + 1][j - 1] 在 dp[i][j]的左下角,如圖:

如果矩陣是從上到下,從左到右遍歷,那麼會用到沒有計算過的dp[i + 1][j - 1],

也就是根據不確定是不是迴文的區間[i+1,j-1],來判斷了[i,j]是不是迴文,那結果一定是不對的。

所以一定要從下到上,從左到右遍歷,這樣保證dp[i + 1][j - 1]都是經過計算的。

5.舉例推導

輸入:"aaa",dp[i][j]狀態如下:

程式碼:

class Solution {
    public int countSubstrings(String s) {
        int len, result = 0;
        len = s.length();
        if (s == null || s.length() < 1) return 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)) { if (j - i <= 1) { result++; dp[i][j] = true; } else if (dp[i + 1][j - 1]) { result++; dp[i][j] = true; } } } } return result; } }