題目
給定一個字串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度為1000。
示例 1:
輸入: "babad"
輸出: "bab"
注意: "aba"也是一個有效答案。
示例 2:
輸入: "cbbd"
輸出: "bb"
複製程式碼
思路
- 暴力法。2層迴圈巢狀,遍歷所有子串。在判斷子串是否為迴文並對比儲存最大的起止下標。通過前後同時擷取字串對比的方式來判斷子串是否為迴文。如果相等,就向兩邊靠攏,直對比的下標相等並且值也相等位置。如果不相等,子串非迴文。
- 中心擴充套件演算法。迴文字串有一個特點,就是左右對稱。如果是奇數長度的迴文字串,中間的字元作為對稱點,如aba中的a。如果是偶數長度的迴文字串,會以中間兩個字元作為對稱點,如abba中的bb。那麼比較的時候,找到中心點,兩邊擴充套件對比就可以了。直到打破對稱,通過暫存的歷史最長迴文子串的起止座標比對當前長度,如果當前子串的長度較大,更新起止座標。由於存在奇偶兩種長度,對應的中心點不一樣,但兩種模式都可能產生回問子串,所有匹配的時候兩種模式都要進行匹配,並取同一個中心點的兩種模式中長度更長的更新起止座標,這個是編碼時需要處理的細節問題。
編碼細節問題
1.為了獲取最後的子串,需要通過暫存起止座標startIndex、endIndex。 2.預設奇數匹配方式,通過判斷當前元素與其後面的元素是否相等來決定是否滿足偶數匹配。
char* longestPalindrome(char* s) {
int startIndex = 0 ;
int endIndex = 0;
int len = strlen(s);
for (int i = 0; i < len; i ++) {
int frontIndex = i ;
int nextIndex = i;
bool evenSerech = true;
//滿足偶數匹配方式
if (s[i] == s[nextIndex + 1]) {
evenSerech = true;
}
while (frontIndex > -1 && nextIndex < len && s[frontIndex] == s[nextIndex]) {
frontIndex --;
nextIndex ++;
}
int current = --nextIndex + 1 - ++frontIndex ;
if (current > (endIndex + 1 - startIndex)) {
startIndex = frontIndex;
endIndex = nextIndex;
}
if (evenSerech) {
frontIndex = i ;
nextIndex = i + 1;
while (frontIndex > -1 && nextIndex < len && s[frontIndex] == s[nextIndex]) {
frontIndex --;
nextIndex ++;
}
int current = --nextIndex + 1 - ++frontIndex ;
if (current > (endIndex + 1 - startIndex)) {
startIndex = frontIndex;
endIndex = nextIndex;
}
}
}
char *p = (char*)malloc(sizeof(char*) * (endIndex + 1 - startIndex));
int j = 0;
for (int i = startIndex; i <= endIndex; i ++) {
p[j ++] = s[i];
}
return p;
}
複製程式碼
小結:需要認真的分析迴文的特點,迴文串分偶數長度與奇數長度兩種情況(認真審題並分析題目所求,不能忽略了一些必要的點,這一點很重要,卡時間比較多的是想通過修改起止指標的位置來適配偶數的模式,發現怎麼都不能同時適配奇偶兩種情況,如果是兩類情況不能簡單的統一處理的話,要變回單獨處理)。另外這題能反轉字串取相同子串的方法(有坑)、動態規劃和Manacher 演算法來處理,後面再學習學習。
待完善L('ω')┘三└('ω')」....