題目描述
給定一個字串 s,找到 s中最長的迴文子串。你可以假設 s 的最大長度為1000。
示例1
輸入: "babad"
輸出: "bab"
注意: "aba"也是一個有效答案。
示例2
輸入: "cbbd"
輸出: "bb"
解題
對於這道題,最簡單的方法就是暴力求解了。對於很多演算法題,我想會暴力求解是最基本的能力,但也絕不能滿足於暴力,而且很多題的暴力解法都是很類似的。
這道題與其他的暴力解法一樣,外面兩層for迴圈遍歷找出所以子串,第三層迴圈用來判斷該子串是否為迴文串。
這種演算法的時間複雜度為O(n3)。這裡我就不給出程式碼了
優化策略
我們可以換一種思想,假如字串為迴文串,那麼把這個字串首尾兩個字元去掉,剩下的子串也會是一個迴文串。
基於這種想法,我們就可以這樣做了:一個for迴圈遍歷所有字元,單個字元也可以是一個迴文串,然後向這個字元的兩邊各自新增一個字元。判斷該字串是否還是迴文串。
例如a是一個迴文串,向a的兩邊新增一個字元,假如新增的這兩個字元相同的話,那麼新增之後的字串還是迴文串,如果兩個字串不同的話,那麼新增之後就不是字串了,。繼續遍歷下一個字元。,,,,,
需要注意的地方
不過這裡有一個需要注意的地方,我們上面是從單個字元的兩邊開始向兩邊擴充新增字元的,這種情況下,最終迴文串字元個數是奇數的,例如aba,cabac。
但是迴文串的字元個數也有可能是偶數的,例如bb,cbbc,那麼對於這種情況,按照單個字元向兩邊擴充的話就會出問題,因此對於這種情況,我們要從s[i],s[i+1]兩邊開始擴充。
知道了思路,可以自己先動手試一下能不能寫出來。
我做的程式碼去下:
public String longestPalindrome(String s) {
//先判斷是否為空或者長度小於1
//把||寫成了&&害我找了好久都不知道錯在哪...
if(s == null || s.length() < 1){
return "";
}
int left = 0;//用來記錄子串的起始位置
int right = 0;//用來記錄子串的末尾位置
for(int i = 0; i < s.length(); i++){
//通過findMore這個方法來擴充
//bab這種情況
int t1 = findMore(s, i, i);//bab這種情況
//abba這種情況
int t2 = findMore(s, i, i+1);
//選出比較長的那個
int max = Math.max(t1, t2);
if(max > right - left){
left = i - (max - 1)/2;
right = i + max/2;
}
}
return s.substring(left, right+1);
}
public int findMore(String s, int left, int right){
while(left >= 0 && right < s.length()
&& s.charAt(left) == s.charAt(right)){
left--;
right++;
}
return right - left - 1;
}
這種方法的時間複雜度為O(n2)。
不過我去看了官方的解答,那裡貌似提供了一個更牛的解法連結,這個解法的時間複雜度為O(n)。假如你有興趣的話,可以去研究下。
連結:https://articles.leetcode.com/longest-palindromic-substring-part-ii/
關注公我的眾號:苦逼的碼農,獲取更多原創文章,後臺回覆禮包送你一份特別的資源大禮包。同時也感謝把文章介紹給更多需要的人。。