題目描述
給定一個字符串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度爲 1000。
示例1:
輸入:“babad”
輸出:“bab”
注意:“aba” 也是一個有效答案。
示例2:
輸入:“bcbbd”
輸出:“bb”
解題思路
思路一:取出所有子串,在子串中找最長迴文子串
迴文字符串:正讀和倒讀都是一樣的順序的字符串就是迴文字符串。那如何判斷最長迴文子串呢?我們可以理解,就是判斷一個字符串的所有子串中,是最長的迴文子串。那麼我們就有了一個解題思路:取出字符串中的所有子串判斷其是否迴文,如果迴文的話判斷其是否是最長的迴文子串。
就有了下面的代碼:
class Solution {
public String longestPalindrome(String s) {
// 迴文子串:正讀和反讀都一樣
// 最長的迴文子串:取出字符串中所有的子串進行判斷是否是迴文子串
// 直接返回的情況:字符串的長度小於2
if(s.length() < 2)
return s;
String result = s.substring(0, 1); // 用於保存返回的字符串
String tmp = null;
String tmp_R = null;
// 截取所有的子串進行比較
for(int i = 0; i < s.length()-1; ++i){
tmp = null;
tmp_R = null;
for(int j = s.length(); j > i; --j){
// 1. 先截取一個字符串,如果截取的子串沒有當前的子串大,就不截取了
if(j - i > result.length()){
tmp = s.substring(i, j);
// 2. 翻轉字符串
tmp_R = new StringBuffer(tmp).reverse().toString();
// 3. 如果兩個子串相同,則將其賦值給result字符串
if(tmp.equals(tmp_R) && tmp.length() > result.length()){
result = tmp;
}
}
}
}
return result;
}
}
當我們在leetcode上的在線oj上運行的時候,會發現這種思路是正確的的,但是當遇到較長字符串的時候會超出時間限制,說明這種方法還是不夠優化,只是最基礎的代碼實現。
思路二:中心擴展算法
觀察迴文子串,我們會發現迴文子串有一個很奇妙的特點,它可以按照它的中心去展開,它按照中心是一一對應的。
通過上面的圖示,我們會發現出現兩種情況,奇數個字符的子串和偶數個字符的子串,他們的情況有些許的不同。由於需要從每個字符開始擴展尋找,我們將該思想寫成一個方法去實現。
我們要實現上述方法的迴文子串,就需要將我們的字符串傳遞,還需要將中心的位置傳遞過去,奇數個的話,傳遞兩個相同的位置;偶數個的話,傳遞兩個緊挨的位置,便於判斷,由於我們不能確定從該字符出擴展,到底有奇數個字符的迴文子串還是偶數個字符的迴文子串,所以我們兩個都要去進行處理。
在找回文子串的時候,我們只需要找到中心位置和迴文子串的長度就可以確定迴文子串啦!!!
代碼實現:
class Solution {
public String longestPalindrome(String s) {
// 長度爲1的字符串本就是迴文字符串
if(s.length() < 2)
return s;
// 使用中心擴展算法向兩邊擴展尋找回文子串,一直找到沒有相同的爲止,但是會出現偶數的子串
int center = 0; // 標記迴文子串的中位置
int maxLength = 0; // 標記迴文子串的長度
for(int i = 0; i < s.length(); i++){
int oddLength = centerString(s, i, i); // 最長迴文子串爲奇數
int evenLength = centerString(s, i, i+1); // 最長迴文子串爲偶數
// 判斷最長迴文子串爲奇數或爲偶數的情況
if(maxLength < Math.max(oddLength, evenLength)){
center = i;
maxLength = Math.max(oddLength, evenLength);
}
}
// 截取回文子串
return s.substring(center-(maxLength - 1)/2, center+maxLength/2+1);
}
// 返回最長迴文子串的長度
private int centerString(String s, int left, int right){
int begin = left;
int end = right;
// 找出迴文子串
while(begin >= 0 && end < s.length() && s.charAt(begin) == s.charAt(end)){
begin--;
end++;
}
// 找到迴文子串的長度,並返回
return end - begin - 1;
}
}