力扣647(迴文子串)
阿新 • • 發佈:2021-12-27
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; } }