Problem Statement:
Given a string s
, your task is to identify and return the longest palindromic substring within s
. A palindromic substring is a sequence of characters that reads the same forwards and backward. You may assume the maximum length of the input string s
is 1000.
Example 1:
Input: s = "babad"
Output: "bab"
or "aba"
(Both are valid as they are longest palindromic substrings of the same length.)
Example 2:
Input: s = "cbbd"
Output: "bb"
Example 3:
Input: s = "a"
Output: "a"
Example 4:
Input: s = "ac"
Output: "a"
Considerations:
Follow-up Questions (Potential):
Provide a well-commented code solution and explain your reasoning. Focus on both correctness and efficiency.
Given a string s
, find the longest palindromic substring in s
. Assume that the maximum length of s
is 1000.
For example:
s
is "babad", one possible answer is "bab". "aba" is also a valid answer.s
is "cbbd", the answer is "bb".s
is "a", the answer is "a".s
is "ac", the answer is "a".Your solution should be efficient and handle various test cases, including empty strings and strings with a single character. A palindromic substring is a substring that reads the same forwards and backward. The goal is to identify the longest such substring within the given input string s
. Consider edge cases and optimize for performance, keeping in mind that the input string's length will not exceed 1000 characters.
A naive approach is to generate all possible substrings of the given string and check each substring for being a palindrome. We keep track of the longest palindromic substring found so far.
def is_palindrome(s):
return s == s[::-1]
def longest_palindrome_brute_force(s):
longest = ""
for i in range(len(s)):
for j in range(i, len(s)):
substring = s[i:j+1]
if is_palindrome(substring):
if len(substring) > len(longest):
longest = substring
return longest
We can solve this problem more efficiently using dynamic programming. Let dp[i][j]
be a boolean value indicating whether the substring s[i:j+1]
is a palindrome. The base cases are substrings of length 1 and 2. Then, we can build up the dp
table by checking if s[i] == s[j]
and dp[i+1][j-1]
is true.
def longest_palindrome_dp(s):
n = len(s)
if n == 0:
return ""
dp = [[False] * n for _ in range(n)]
start = 0
max_len = 1
# Base case: single-character palindromes
for i in range(n):
dp[i][i] = True
# Base case: two-character palindromes
for i in range(n - 1):
if s[i] == s[i+1]:
dp[i][i+1] = True
start = i
max_len = 2
# Check for palindromes of length 3 or more
for k in range(3, n + 1):
for i in range(n - k + 1):
j = i + k - 1
if s[i] == s[j] and dp[i+1][j-1]:
dp[i][j] = True
if k > max_len:
start = i
max_len = k
return s[start:start + max_len]
This approach iterates through each character in the string and treats it as a potential center of a palindrome. We expand around each center to find the longest palindrome centered at that character.
def expand_around_center(s, left, right):
while left >= 0 and right < len(s) and s[left] == s[right]:
left -= 1
right += 1
return left + 1, right - 1
def longest_palindrome_expand_center(s):
if not s:
return ""
start = 0
end = 0
for i in range(len(s)):
# Odd length palindrome
left1, right1 = expand_around_center(s, i, i)
len1 = right1 - left1 + 1
# Even length palindrome
left2, right2 = expand_around_center(s, i, i + 1)
len2 = right2 - left2 + 1
if len1 > len2:
max_len = len1
l = left1
r = right1
else:
max_len = len2
l = left2
r = right2
if max_len > (end - start + 1):
start = l
end = r
return s[start:end + 1]
The brute force solution has a time complexity of O(n^3), where n is the length of the string s
. This is because we generate all possible substrings (O(n^2)) and then check if each substring is a palindrome (O(n)).
The dynamic programming solution has a time complexity of O(n^2), where n is the length of the string s
. This is because we fill the dp
table, which takes O(n^2) time. The process of finding the longest palindrome from the table takes O(1) time.
The expand around center solution has a time complexity of O(n^2), where n is the length of the string s
. This is because, in the worst case, we might need to expand from each character to the ends of the string.
The brute force solution has a space complexity of O(1), as we are only storing the longest palindrome found so far and some temporary variables.
The dynamic programming solution has a space complexity of O(n^2), where n is the length of the string s
. This is because we need to store the dp
table, which is of size n x n.
The expand around center solution has a space complexity of O(1), as we are only storing a few variables to keep track of the longest palindrome.
s
is empty, the longest palindromic substring is an empty string.s
contains only one character, that character is the longest palindromic substring.s
does not contain any palindromic substring (e.g., "abcde"), the longest palindromic substring is a single character from the string.