5. Longest Palindromic Substring: Unraveling the Palindromic Puzzle 🧩
Hey fellow coders! 👋 Today, we're diving into a LeetCode classic that often stumps beginners but reveals a really elegant pattern once you spot it: the Longest Palindromic Substring problem.
Don't let the fancy name scare you! We'll break it down piece by piece, find an intuitive way to tackle it, and emerge victorious with a neat, efficient solution. Ready? Let's go!
📜 Problem Explanation
The problem asks us to find the longest palindromic substring within a given string s.
"Whoa, hold on!" you might say. "What's a palindrome? And what's a substring?" Great questions!
- Palindrome: A string that reads the same forwards and backward. Think words like "madam", "racecar", or even single letters like "a".
- Substring: A contiguous sequence of characters within a string. For "babad", "bab", "aba", "bad", "a" are all substrings. "bba" is not a substring because the 'b's aren't contiguous in that order.
So, our mission is to scan through the given string s, find all possible substrings that are also palindromes, and then return the longest one among them.
Let's look at the examples:
- Example 1:
s = "babad"- Possible palindromic substrings: "b", "a", "b", "a", "d", "bab", "aba".
- The longest ones are "bab" and "aba". Either is a valid answer.
- Example 2:
s = "cbbd"- Possible palindromic substrings: "c", "b", "b", "d", "bb".
- The longest is "bb".
Constraints:
- The string
swill have between 1 and 1000 characters. - It will only contain digits and English letters. No weird symbols to worry about!
🤔 Intuition: Don't Brute Force, Explore From the Middle!
A common first thought for many string problems is: "Let's check every possible substring!"
If you have a string of length N:
- There are
N * (N + 1) / 2possible substrings (e.g., for "abc", "a", "b", "c", "ab", "bc", "abc"). - For each substring, checking if it's a palindrome takes
O(length_of_substring)time. - This quickly leads to an
O(N^3)solution, which forN=1000is1000^3 = 1,000,000,000operations – way too slow! 🐌
We need something smarter.
What makes a palindrome special? It's symmetrical around its center!
Consider "racecar":
r a c e c a r
The e is the center. Everything expands outwards equally.
Consider "abba":
a b b a
The "center" is between the two bs.
This gives us a huge hint! Instead of picking two ends and checking inwards, what if we pick a center and expand outwards?
Every palindrome has a center:
- Odd-length palindromes: A single character is the center (e.g., 'a' in "bab", 'e' in "racecar").
- Even-length palindromes: The "center" is the space between two identical characters (e.g., the space between the two 'b's in "bb", or "abba").
This means we can iterate through every possible "center" in our string and try to expand outwards to find the longest palindrome centered there. Since there are N characters and N-1 spaces between characters, there are roughly 2N - 1 potential centers.
🚀 Approach: Expand Around Center
Our intuition leads us to a solid plan:
- We'll maintain variables
startandmax_lento keep track of the beginning index and length of the longest palindrome we've found so far. Initializestart = 0andmax_len = 1(a single character is always a palindrome). - We'll iterate through each character in the string
susing an indexi. For eachi, we consider it as a potential center for a palindrome. - Since palindromes can be odd or even length, we'll need to check two types of expansions for each
i:- Odd length:
iitself is the center. We'll try to expand outwards fromleft = i,right = i. - Even length: The space after
iis the center. We'll try to expand outwards fromleft = i,right = i + 1.
- Odd length:
- To avoid repeating code, we'll create a helper function, let's call it
expandAroundCenter(s, left, right). This function will take the stringsand two pointers,leftandright, and expand them outwards as long as:-
leftis not less than 0 (we're within string bounds). -
rightis not greater than or equal tolen(s)(we're within string bounds). -
s[left]is equal tos[right](the characters match, so it's still a palindrome). - Once these conditions are no longer met, the function returns the length of the palindrome found (which is
right - left - 1).
-
- In our main loop, after calling
expandAroundCenterfor both odd and even cases, we'll compare the lengths of the palindromes found. If either is longer than our currentmax_len, we updatemax_lenand calculate the newstartindex. Thestartindex will bei - (current_palindrome_length - 1) // 2. (This formula looks tricky, but it simply finds the leftmost character of the new longest palindrome given its length and its "center"i). - After checking all possible centers, we return the substring
s[start : start + max_len].
Let's trace s = "babad":
- Initialize
start = 0,max_len = 1(our initial "b") - i = 0 (char 'b')
-
expandAroundCenter(s, 0, 0)-> returns length 1 ("b") -
expandAroundCenter(s, 0, 1)-> 'b' != 'a', returns length 0
-
- i = 1 (char 'a')
-
expandAroundCenter(s, 1, 1)-> returns length 1 ("a") -
expandAroundCenter(s, 1, 2)-> 'a' == 'b' NO, returns length 0 -
expandAroundCenter(s, 0, 2)for center 'a':s[0]=='b',s[2]=='b'.leftbecomes -1,rightbecomes 3. Palindrome is "bab", length 3.-
max_len= 3,start=1 - (3-1)//2=1 - 1= 0. Current best: "bab".
-
-
- i = 2 (char 'b')
-
expandAroundCenter(s, 2, 2)-> returns length 1 ("b") -
expandAroundCenter(s, 2, 3)-> 'b' != 'a', returns length 0 -
expandAroundCenter(s, 1, 3)for center 'b':s[1]=='a',s[3]=='a'.leftbecomes 0,rightbecomes 4. Palindrome is "aba", length 3.- Length is 3, same as current
max_len. We don't need to updatestartandmax_lenif it's not strictly greater, but it's fine if we do (it would become "aba"). Let's say it updates to "aba".
- Length is 3, same as current
-
- ... and so on.
Finally, we return s[start : start + max_len].
💻 Code
class Solution:
def longestPalindrome(self, s: str) -> str:
if not s:
return ""
# Helper function to expand around a center
# It takes the string s, and the left and right pointers
# It expands outwards as long as characters match and stay within bounds
# Returns the length of the palindrome found
def expandAroundCenter(left: int, right: int) -> int:
while left >= 0 and right < len(s) and s[left] == s[right]:
left -= 1
right += 1
# After the loop, left and right are one step *past* the palindrome
# So, the length is (right - 1) - (left + 1) + 1 = right - left - 1
return right - left - 1
start_index = 0 # Stores the starting index of the longest palindrome
max_length = 0 # Stores the maximum length found so far
# Loop through each character to consider it as a center
for i in range(len(s)):
# Case 1: Odd length palindrome (e.g., "aba", "racecar")
# The current character s[i] is the center
len1 = expandAroundCenter(i, i)
# Case 2: Even length palindrome (e.g., "abba", "bb")
# The center is between s[i] and s[i+1]
len2 = expandAroundCenter(i, i + 1)
# Get the maximum length found from these two expansions
current_max_len = max(len1, len2)
# If this palindrome is longer than our current max_length
if current_max_len > max_length:
max_length = current_max_len
# Calculate the new starting index for this longest palindrome
# For an odd length palindrome, start = i - (length - 1) / 2
# For an even length palindrome, start = i - (length / 2 - 1)
# Both can be generalized as: i - (length - 1) // 2
start_index = i - (max_length - 1) // 2
# Return the substring from start_index with max_length
return s[start_index : start_index + max_length]
⏱️ Time & Space Complexity Analysis
Let's break down how efficient our solution is:
-
Time Complexity:
O(N^2)- The main
forloop iteratesNtimes (once for each character ins). - Inside the loop, we call
expandAroundCentertwice. - The
expandAroundCenterfunction, in the worst case (e.g.,s = "aaaaa"), might expand all the way to the boundaries of the string. This takesO(N)time. - Therefore, the total time complexity is
N * O(N) = O(N^2). - Given
N <= 1000,N^2is1,000,000, which is perfectly acceptable within typical time limits (usually around10^8operations per second).
- The main
-
Space Complexity:
O(1)- We are only using a few constant variables (
start_index,max_length,i,len1,len2,left,right). We are not storing any data structures that grow with the input sizeN. - The slicing
s[start_index : start_index + max_length]creates a new string, but this is part of the output, not auxiliary space used by the algorithm itself.
- We are only using a few constant variables (
🌟 Key Takeaways
- Don't Jump to Brute Force: Always consider the constraints and think about whether a naive
O(N^3)orO(N^2)approach will pass. Often, there's a more elegant pattern waiting to be discovered! - Palindromes and Symmetry: The core idea for many palindrome problems revolves around their symmetrical nature. Thinking about "centers" is a powerful paradigm.
- Odd vs. Even Length: Remember that palindromes can have either odd or even lengths, and your solution needs to account for both types of "centers."
- Helper Functions: Breaking down complex logic into smaller, reusable helper functions (like
expandAroundCenter) makes your code cleaner, more readable, and easier to debug. - Smallest Palindrome is 1: Don't forget that a single character is always a palindrome, which can be useful for initializing
max_length.
This problem is a fantastic introduction to dynamic programming and string algorithms, and mastering the "expand around center" technique will serve you well in many other coding challenges!
Happy coding! ✨
Submission Details
- Author Account: aryan-subudhi
- Publishing Time: 2026-05-25 23:24:13
Top comments (0)