Leetcode5: Longest Palindromic Substring(最長迴文子串)
LeetCode:https://leetcode.com/problems/longest-palindromic-substring/
LeetCodeCn:https://leetcode-cn.com/problems/longest-palindromic-substring/
題目描述
給定一個字串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度為 1000。
示例
-
示例 1:
- 輸入: "babad"
- 輸出: "bab"
- 注意: "aba" 也是一個有效答案。
-
示例 2:
- 輸入: "cbbd"
- 輸出: "bb"
解題方法
感覺暴力法什麼的,可以不再說了
中心擴充套件法
如果一個子串是迴文,那麼它本事是一個左右對稱的形式,長度為n的子串,其中心有2n-1個,因為長度為偶數的子串,其中心可能在兩個文字中間.接下來我們只要依次查詢每個子串元素和兩個元素中間作為迴文子串的中心,記錄其中最長的子串資訊.
圖解相關思路
在正式開始之前,我們先看一下如何查詢一箇中心能匹配的迴文最長長度是如何得到的.
前面提到,奇數長度的迴文串和偶數長度的迴文串其中心是不同,在查詢的過程中我們要分別區分兩種情況來理解.
假設其長度為奇數,說明中心位置的元素無需和其它元素匹配(因為本身和本身一定相等),檢測其左右相同長度的元素是否相等,如下圖,假設中心位置是第1位的a,其左右元素相同,分別減少l和增加r,當時此時l = -1,並不合法,所以第1位作為中心的最長迴文長度為3.
假設其長度為偶數,相當於其中心是一個空元素,也一定與本身相同,我們直接檢測其兩側的元素是否相同,步驟同上.
我們將"babab"作為引數,此時start(最長子串的開始位置)預設為0,end(最長子串的結束位置)預設為0.
當我們搜尋第0位時,len(奇) = 1, len(偶) = 0,其最大回文子串長度為1,大於當前start和end之間的差.我們需要更新statr和end的內容.end需要在i的基礎上增加len/2,start需要在i的基礎上減去(len - 1) /2,(防止偶數子串引起的越界問題).
我們繼續移動i,當i = 1時,此時其最長子串為3,更新start值為0,end值為2.
後邊內容不重複, 因為每次計算相對來說都是獨立,只需要將此為得到的最長迴文子串長度和已知的比對即可
程式碼實現
public String longestPalindrome(String s) {
if (s == null || s.length() < 1){
return "";
}
int start = 0, end = 0;
for (int i = 0; i < s.length(); i++) {
int len = Math.max(isCenterNum(s, i , i), isCenterNum(s , i, i+1));
if (len > end - start){
start = i - (len - 1) / 2;
end = i + len / 2;
}
}
return s.substring(start, end + 1);
}
//計算某位中中心的最長迴文子串方法
public int isCenterNum(String s, int l, int r){
while (l >= 0 && r < s.length() && (s.charAt(l) == s.charAt(r))) {
l--;
r++;
}
return r - l - 1;
}
複製程式碼
相關程式碼歡迎大家關注並提出改進的建議