Longest Palindromic Substring
Problem
Given a string s, return the longest palindromic substring in s.
- 1 ≤ s.length ≤ 1000
- s consists of ASCII characters
Example
s = "babad""bab"The brute-force approach would check every substring to see if it is a palindrome, which is O(n^3) due to substring extraction and palindrome checks. Instead, the optimal strategy expands around potential palindrome centers. For example, at index 1 ('a'), the algorithm expands left and right to check for odd-length palindromes like 'bab'. Similarly, it checks even-length palindromes by expanding around pairs of characters. The critical moment is when the algorithm finds a palindrome longer than the current longest and updates the result accordingly. This approach reduces the complexity to O(n^2) by avoiding repeated substring checks and leveraging symmetry.
Approach
Straightforward Solution
Check every substring and verify if it is a palindrome by comparing characters from both ends. This brute-force approach is O(n^3) due to O(n^2) substrings and O(n) palindrome checks, which is inefficient for large inputs.
Core Observation
A palindrome reads the same forwards and backwards. Any palindrome can be expanded from its center. Since palindromes can be odd or even length, centers can be single characters or pairs of characters.
Path to Optimal
The key recognition signals are 'longest palindromic substring' and 'substring' (contiguous), which suggest expanding around centers. Instead of checking all substrings, the algorithm treats each index (and each pair of adjacent indices) as a potential palindrome center and expands outwards while characters match. This reduces redundant checks and leverages the palindrome's symmetric property.
Optimal Approach
Iterate through each index in the string, expanding around it to find the longest odd-length palindrome, then expand around the gap between this index and the next to find the longest even-length palindrome. Track the longest palindrome found and update the result accordingly. This approach runs in O(n^2) time and O(1) auxiliary space, which is optimal for this problem.
Time
O(n^2)
For each of the n indices, the algorithm expands outward at most n times in the worst case, resulting in O(n^2) total operations.
Space
O(1)
Only a few variables are used to track indices and the current longest palindrome; no additional data structures proportional to input size are needed.
Pattern Spotlight
Two Pointers (Expand Around Center)
To find palindromes efficiently, treat each character and each gap between characters as a center and expand pointers outward symmetrically until the palindrome property breaks, thereby avoiding redundant substring checks.
Solution
| 1 | class Solution:
|
| 2 | def longestPalindrome(self, s: str) -> str:
|
| 3 | res = ""
|
| 4 | res_len = 0
|
| 5 |
|
| 6 | for i in range(len(s)):
|
| 7 | l, r = i, i
|
| 8 | while l >= 0 and r < len(s) and s[l] == s[r]:
|
| 9 | if (r - l + 1) > res_len:
|
| 10 | res = s[l:r+1]
|
| 11 | res_len = r - l + 1
|
| 12 | l -= 1
|
| 13 | r += 1
|
| 14 |
|
| 15 | l, r = i, i + 1
|
| 16 | while l >= 0 and r < len(s) and s[l] == s[r]:
|
| 17 | if (r - l + 1) > res_len:
|
| 18 | res = s[l:r+1]
|
| 19 | res_len = r - l + 1
|
| 20 | l -= 1
|
| 21 | r += 1
|
| 22 |
|
| 23 | return res |
Step-by-Step Solution
Initialize Result Variables to Track Longest Palindrome
| 3 | res = ""
|
| 4 | res_len = 0
|
Objective
To prepare variables that store the longest palindrome substring found and its length.
Key Insight
Tracking the longest palindrome and its length allows the algorithm to update the result only when a longer palindrome is found during expansions. Initializing with empty string and zero length ensures correctness even for single-character inputs.
Interview Quick-Check
Core Logic
The variables `res` and `res_len` maintain the current longest palindrome substring and its length, enabling efficient updates.
State & Boundaries
Starting with an empty string and zero length handles edge cases where the input string length is 1.
Expand Around Single Character Centers to Find Odd-Length Palindromes
| 6 | for i in range(len(s)):
|
| 7 | l, r = i, i
|
| 8 | while l >= 0 and r < len(s) and s[l] == s[r]:
|
| 9 | if (r - l + 1) > res_len:
|
| 10 | res = s[l:r+1]
|
| 11 | res_len = r - l + 1
|
| 12 | l -= 1
|
| 13 | r += 1
|
Objective
To find the longest odd-length palindrome centered at each index by expanding pointers outward symmetrically.
Key Insight
Odd-length palindromes have a single center character. By initializing left and right pointers at the same index and expanding outward while characters match, the algorithm efficiently finds the longest palindrome centered at that character without checking all substrings explicitly.
Interview Quick-Check
Core Logic
Expanding pointers `l` and `r` outward while `s[l] == s[r]` captures the maximal odd-length palindrome centered at index `i`.
State & Boundaries
The expansion stops when pointers go out of bounds or characters differ, ensuring only valid palindromes are considered.
Common Pitfalls & Bugs
Forgetting to update the result when a longer palindrome is found leads to incorrect answers.
Expand Around Adjacent Character Pairs to Find Even-Length Palindromes
| 15 | l, r = i, i + 1
|
| 16 | while l >= 0 and r < len(s) and s[l] == s[r]:
|
| 17 | if (r - l + 1) > res_len:
|
| 18 | res = s[l:r+1]
|
| 19 | res_len = r - l + 1
|
| 20 | l -= 1
|
| 21 | r += 1
|
Objective
To find the longest even-length palindrome centered between each pair of adjacent characters by expanding pointers outward symmetrically.
Key Insight
Even-length palindromes have two center characters. By initializing left pointer at index `i` and right pointer at `i+1`, the algorithm expands outward while characters match, capturing all even-length palindromes efficiently without redundant checks.
Interview Quick-Check
Core Logic
Expanding pointers `l` and `r` outward from adjacent indices captures the maximal even-length palindrome centered between `i` and `i+1`.
State & Boundaries
Expansion halts when pointers go out of bounds or characters differ, ensuring correctness.
Common Pitfalls & Bugs
Neglecting even-length palindromes results in missing valid longer palindromes.
Return the Longest Palindromic Substring Found
| 23 | return res |
Objective
To output the longest palindrome substring after all expansions have been checked.
Key Insight
After iterating through all possible centers and updating the longest palindrome, returning the stored result provides the correct answer. This final step consolidates all previous computations.
Interview Quick-Check
Core Logic
Returning `res` outputs the longest palindrome substring found during the expansions.
Line Analysis
This solution has 2 Critical lines interviewers watch for.
while l >= 0 and r < len(s) and s[l] == s[r]:
Expand pointers outward while within bounds and characters at pointers match.
Expanding outward symmetrically from the center is the core mechanism that efficiently finds palindromes without checking all substrings.
while l >= 0 and r < len(s) and s[l] == s[r]:
Expand pointers outward while within bounds and characters at pointers match for even-length palindrome.
This expansion is critical to capture even-length palindromes, which would be missed if only single centers were considered.
if (r - l + 1) > res_len:
Check if the current palindrome length exceeds the longest found so far.
This condition ensures the algorithm only updates the result when a strictly longer palindrome is found, maintaining correctness.
res = s[l:r+1]
Update the result substring to the current longest palindrome.
Storing the substring immediately upon finding a longer palindrome ensures the final output is correct and up-to-date.
if (r - l + 1) > res_len:
Check if the current palindrome length exceeds the longest found so far.
Ensures the algorithm updates the result only when a longer palindrome is found, preserving correctness.
res = s[l:r+1]
Update the result substring to the current longest palindrome.
Capturing the substring immediately upon discovery guarantees the final output is the longest palindrome.
l, r = i, i
Set left and right pointers to the current index for odd-length palindrome expansion.
Initializing both pointers at the same index targets palindromes with a single center character.
res_len = r - l + 1
Update the length of the longest palindrome found.
Maintaining the length allows efficient comparisons in subsequent iterations without recomputing substring lengths.
l, r = i, i + 1
Set left pointer to current index and right pointer to the next index for even-length palindrome expansion.
Initializing pointers at adjacent indices targets palindromes with two center characters, covering even-length cases.
res_len = r - l + 1
Update the length of the longest palindrome found.
Maintaining the length allows efficient future comparisons without recomputing substring lengths.
return res
Return the longest palindromic substring found.
After all expansions, returning the stored result provides the correct longest palindrome substring.
res_len = 0
Initialize the length of the longest palindrome to zero.
Tracking the length allows efficient comparison to update the longest palindrome only when a longer one is found.
for i in range(len(s)):
Iterate through each character index in the string as a potential palindrome center.
Each index serves as a candidate center for odd-length palindromes, ensuring all possibilities are explored.
l -= 1
Move the left pointer one step left to expand the palindrome.
Moving left pointer outward is essential to check the next potential palindrome boundary on the left side.
r += 1
Move the right pointer one step right to expand the palindrome.
Moving right pointer outward complements the left pointer movement, maintaining symmetric expansion.
l -= 1
Move the left pointer one step left to expand the palindrome.
Expanding the left boundary is necessary to check for larger palindromes.
r += 1
Move the right pointer one step right to expand the palindrome.
Expanding the right boundary complements the left pointer movement, maintaining symmetry.
res = ""
Initialize an empty string to store the longest palindrome found.
Starting with an empty string ensures the algorithm can update the result as soon as it finds any palindrome, including single characters.
Test Your Understanding
Why does expanding around centers guarantee finding all palindromic substrings without missing any?
Because every palindrome has a center (either a single character for odd-length or a pair for even-length), expanding around all possible centers ensures all palindromes are considered exactly once.
Related Problems
Two Pointers pattern
Don't just read it. Drill it.
Reconstruct Longest Palindromic Substring from memory until it sticks. AlgoDrill blanks out key lines and makes you fill them back in, step by step.
Unlock the Longest Palindromic Substring drill