1. 題目
2. 題意
題目比較好理解,即計算出有多少個迴文子串,同時位置不同的相同迴文子串,將被視爲兩個。
3.方法一
3.1 思路
因爲位置不同的迴文子串需要被重複計數,比較簡單的想法,就是將所有的可能的組合都列出來,並判斷每一種是否是迴文子串。這樣代碼思路比較簡單,但運行時間一定是較長,根據這個思路可再進一步簡化。
對於迴文子串的判斷,我們一般簡單的辦法是從中間向兩邊進行擴展,即對於a,b,c,b,a,如果拿單個c的時候,我們判斷爲迴文子串,此時將其左右納入,即bcb的子串,再判斷也爲迴文子串,則再將左右納入,即abcba的子串,這個思路與前面將所有情況都列舉的思路實質上相同,只是我們可以通過一定的方法減少部分情況的判斷。思路教簡單,下面是該思路的代碼。
3.2 代碼
public int countSubstrings(String s) {
int num = 0;
char[] a = s.toCharArray();
// 注意,這裏需根據子串長度的奇偶分兩種情況
for (int i = 0; i < s.length(); i++) {
num += count(a, i, i);
num += count(a, i, i + 1);
}
return num;
}
private int count(char[] a, int left, int right) {
int num = 0;
// 當某個子串是迴文子串時,向左右兩側擴展,直至不再是迴文子串或超過數據越界
while (left >= 0 && right < a.length && a[left] == a[right]) {
num++;
left--;
right++;
}
return num;
}
3.3 運行結果
4 方法二
4.1 思路
這道題也可以使用動態規劃的思路進行解答,思路其實類似思路一,只是寫成動態規劃的思路。假設[i,j]表示從第i位置到第j位置的子串,那麼我們要判斷[i,j]是迴文子串時,根據思路一的思路,我們需要判斷兩個條件:①[i+1,j-1]是迴文子串 ②i位置的字符與j位置的字符相同。演變成動態規劃那種寫法就是:dp[i][j]
爲true的條件是:dp[i+1][j-1] == true && s[i] == s[j]
。
4.2 代碼
public int countSubstrings1(String s) {
if (s == null) {
return 0;
}
int num = 0;
// dp[i][j]爲true代表:以下標i爲起點,下標j爲終點的子串爲迴文子串
boolean dp[][] = new boolean[s.length()][s.length()];
for (int i = s.length() - 1; i >= 0; i--) {
for (int j = i; j < s.length(); j++) {
if (s.charAt(i) == s.charAt(j) && ((j - i <= 2) || (dp[i + 1][j - 1]))) {
dp[i][j] = true;
num++;
}
}
}
return num;
}