[Medium] 5. Longest Palindromic Substring
Given a string s, return the longest palindromic substring in s.
A palindrome is a string that reads the same backward as forward.
Examples
Example 1:
Input: s = "babad"
Output: "bab"
Explanation: "aba" is also a valid answer.
Example 2:
Input: s = "cbbd"
Output: "bb"
Example 3:
Input: s = "a"
Output: "a"
Constraints
1 <= s.length <= 1000sconsist of only digits and English letters.
Solution Approaches
There are several approaches to solve this problem:
- Expand Around Center: For each position, expand outward to find palindromes (O(n²) time, O(1) space)
- Manacher’s Algorithm: Linear time algorithm using preprocessing (O(n) time, O(n) space)
- Dynamic Programming: Build a DP table to track palindromes (O(n²) time, O(n²) space)
Approach 1: Expand Around Center (Recommended for Interviews)
Time Complexity: O(n²)
Space Complexity: O(1)
The key insight is that every palindrome expands from a center. For each position, we check:
- Odd-length palindromes: Center at a single character (e.g., “aba” centered at ‘b’)
- Even-length palindromes: Center between two characters (e.g., “abba” centered between two ‘b’s)
Approach 2: Manacher’s Algorithm (Optimal)
Time Complexity: O(n)
Space Complexity: O(n)
Uses preprocessing to transform the string and then uses symmetry properties to avoid redundant checks.
Thinking Process
- Two Types of Centers: Odd-length (single char) and even-length (between chars)
- Define state: what subproblem does
dp[i](ordp[i][j]) represent? - Recurrence: how does the answer build from smaller indices?
- Base cases first; optimize space if only prior row/layer is needed.
Common Approaches
Typical techniques for this pattern:
| Approach | Time | Space | Notes |
|---|---|---|---|
| Opposite ends (this problem) | O(n) | O(1) | Sorted array pair search, reversal |
| Slow / fast pointers | O(n) | O(1) | Linked list middle, cycle detection |
| Same-direction chase | O(n) | O(1) | Remove duplicates in-place |
| Sliding window (variable) | O(n) | O(1) | Subarray with constraint |
Solution
class Solution:
def longestPalindrome(self, s):
n = len(s)
if n < 2:
return s
start = 0
maxLen = 1
for i in range(n):
self.expandAroundCenter(s, i, i, start, maxLen)
self.expandAroundCenter(s, i, i + 1, start, maxLen)
return s[start:start + maxLen]
def expandAroundCenter(self, s, left, right, start, maxLen):
n = len(s)
while left >= 0 and right < n and s[left] == s[right]:
length = right - left + 1
if length > maxLen:
# update via list trick (since ints are immutable in Python)
start = left
maxLen = length
left -= 1
right += 1
Algorithm Explanation:
- Initialize (Lines 4-6):
- Handle edge case: if string length < 2, return the string itself
- Initialize
start = 0andmaxLen = 1to track the longest palindrome found
- For Each Position (Lines 7-10):
- Check odd-length palindromes: Expand from
(i, i)- center at single character - Check even-length palindromes: Expand from
(i, i+1)- center between two characters
- Check odd-length palindromes: Expand from
- Expand Function (Lines 13-22):
- Expand outward: While characters match and within bounds, expand
left--andright++ - Update maximum: If current palindrome length >
maxLen, updatestartandmaxLen - Stop when mismatch: Stop expanding when characters don’t match or out of bounds
- Expand outward: While characters match and within bounds, expand
Why This Works:
- Two types of centers: Handles both odd and even length palindromes
- Greedy expansion: For each center, expands as far as possible
- Optimal tracking: Updates the longest palindrome found so far
Example Walkthrough:
For s = "babad":
Initial: start = 0, maxLen = 1
i = 0: Check "b"
- Odd: expandAroundCenter(0, 0) → "b" (len=1, no update)
- Even: expandAroundCenter(0, 1) → "ba" (no match, stop)
i = 1: Check "a"
- Odd: expandAroundCenter(1, 1) → "a" → "bab" (len=3, update: start=0, maxLen=3)
- Even: expandAroundCenter(1, 2) → "ab" (no match, stop)
i = 2: Check "b"
- Odd: expandAroundCenter(2, 2) → "b" → "aba" (len=3, no update, same length)
- Even: expandAroundCenter(2, 3) → "ba" (no match, stop)
i = 3: Check "a"
- Odd: expandAroundCenter(3, 3) → "a" (len=1, no update)
- Even: expandAroundCenter(3, 4) → "ad" (no match, stop)
i = 4: Check "d"
- Odd: expandAroundCenter(4, 4) → "d" (len=1, no update)
- Even: expandAroundCenter(4, 5) → out of bounds
Result: s.substr(0, 3) = "bab"
Complexity Analysis:
- Time Complexity: O(n²)
- For each of n positions, we expand outward
- In worst case, expansion can go up to n/2 in each direction
- Total: O(n × n) = O(n²)
- Space Complexity: O(1)
- Only using a few variables:
start,maxLen,left,right
- Only using a few variables:
Common Mistakes
- Single character:
"a"→ return"a" - All same characters:
"aaa"→ return"aaa" - No palindrome > 1:
"abc"→ return"a"(or any single char) -
Two palindromes of same length:
"babad"→ return either"bab"or"aba" - Missing even-length palindromes: Forgetting to check centers between characters
- Index out of bounds: Not checking bounds before accessing array
- Wrong expansion logic: Not expanding symmetrically from center
- Manacher’s preprocessing: Forgetting to convert back to original indices
Related Problems
- LC 647: Palindromic Substrings - Count all palindromic substrings (same expand-around-center technique)
- LC 516: Longest Palindromic Subsequence - Find longest palindromic subsequence (DP)
- LC 125: Valid Palindrome - Check if string is palindrome
- LC 680: Valid Palindrome II - Can make palindrome with 1 deletion
Key Takeaways
- Two Types of Centers: Odd-length (single char) and even-length (between chars)
- Expand Greedily: For each center, expand as far as possible
- Manacher’s Symmetry: Use previously computed palindromes to avoid redundant checks
- Preprocessing: Transform string to handle even-length palindromes uniformly
References
- LC 5: Longest Palindromic Substring on LeetCode
- LeetCode Discuss — LC 5: Longest Palindromic Substring
- LeetCode Editorial (may require premium)