給定一個字串,找出其中最長的回文子串。回文是指正著讀與反著讀都相同的字串,例如 "madam"、"racecar" 或中文的 "上海自來水來自海上"。
public boolean isPalindrome(String s) {
if (s == null) return false;
int left = 0, right = s.length() - 1;
while (left < right) {
if (s.charAt(left) != s.charAt(right)) return false;
left++;
right--;
}
return true;
}
private String reverse(String str) {
StringBuilder sb = new StringBuilder(str);
return sb.reverse().toString();
}
public boolean isPalindrome2(String s) {
return s.equals(reverse(s));
}
雙重迴圈枚舉所有子串,對每個子串呼叫 isPalindrome 判斷,記錄最長者。適合字串長度較小(< 100)的情況。
觀察回文特性:以某字元或兩字元間隙為中心,向兩側擴展。遍歷每個可能的中心(共 2n-1 個),擴展並更新最長回文。
public String longestPalindrome(String s) {
if (s == null || s.length() < 2) return s;
int start = 0, maxLen = 1;
for (int i = 0; i < s.length(); i++) {
// 奇數長度:以 i 為中心
expand(s, i, i, start, maxLen);
// 偶數長度:以 i, i+1 為中心
expand(s, i, i + 1, start, maxLen);
}
return s.substring(start, start + maxLen);
}
private void expand(String s, int left, int right, int[] start, int[] maxLen) {
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
left--; right++;
}
// 實際回文範圍為 (left+1) 到 (right-1)
int len = right - left - 1;
if (len > maxLen[0]) {
maxLen[0] = len;
start[0] = left + 1;
}
}
利用回文對稱性避免重複比較,可在線性時間內解決。適合極長字串(> 10⁴)或競賽程式設計。實作較複雜,此處不贅述,有興趣可自行搜尋。
public class LongestPalindromeDemo {
public static void main(String[] args) {
String input = "babad"; // 預期輸出 "bab" 或 "aba"
System.out.println("最長回文子串: " + longestPalindrome(input));
}
// ... 請填入上述 longestPalindrome 與 expand 方法
}
| 演算法 | 時間複雜度 | 空間複雜度 | 適用場景 |
|---|---|---|---|
| 暴力枚舉 | O(n³) | O(1) | 教學示範、極短字串 |
| 中心擴展 | O(n²) | O(1) | 通用場景、面試首選、字串長度 ≤ 10⁴ |
| Manacher | O(n) | O(n) | 超長字串、高頻呼叫、競賽程式 |
left >= 0 && right < len。