I've done a lot of Leetcode questions lately. When I failed to do some question, I've always knew why, but not this time - question 5. Longest Palindromic Substring:
Given a string s, return the longest palindromic substring in s.
Example 1:
Input: s = "babad"
Output: "bab"
Explanation: "aba" is also a valid answer.
Example 2:
Input: s = "cbbd"
Output: "bb"
My code:
class Solution:
def longestPalindrome(self, s: str) -> str:
def is_palindrom(word):
for i,letter in enumerate(word):
if letter != word[-i-1]:
return False
return True
out = ""
checked_words = set()
def dp(word):
nonlocal out
if len(word)>len(out) and word not in checked_words:
checked_words.add(word)
if is_palindrom(word) and len(word)>len(out):
out = word
dp(word[:-1])
dp(word[1:])
dp(s)
return out
Issue: Memory Limit Exceeded on imput: s = "rgczcpratwyqxaszbuwwcadruayhasynuxnakpmsyhxzlnxmdtsqqlmwnbxvmgvllafrpmlfuqpbhjddmhmbcgmlyeypkfpreddyencsdmgxysctpubvgeedhurvizgqxclhpfrvxggrowaynrtuwvvvwnqlowdihtrdzjffrgoeqivnprdnpvfjuhycpfydjcpfcnkpyujljiesmuxhtizzvwhvpqylvcirwqsmpptyhcqybstsfgjadicwzycswwmpluvzqdvnhkcofptqrzgjqtbvbdxylrylinspncrkxclykccbwridpqckstxdjawvziucrswpsfmisqiozworibeycuarcidbljslwbalcemgymnsxfziattdylrulwrybzztoxhevsdnvvljfzzrgcmagshucoalfiuapgzpqgjjgqsmcvtdsvehewrvtkeqwgmatqdpwlayjcxcavjmgpdyklrjcqvxjqbjucfubgmgpkfdxznkhcejscymuildfnuxwmuklntnyycdcscioimenaeohgpbcpogyifcsatfxeslstkjclauqmywacizyapxlgtcchlxkvygzeucwalhvhbwkvbceqajstxzzppcxoanhyfkgwaelsfdeeviqogjpresnoacegfeejyychabkhszcokdxpaqrprwfdahjqkfptwpeykgumyemgkccynxuvbdpjlrbgqtcqulxodurugofuwzudnhgxdrbbxtrvdnlodyhsifvyspejenpdckevzqrexplpcqtwtxlimfrsjumiygqeemhihcxyngsemcolrnlyhqlbqbcestadoxtrdvcgucntjnfavylip"
I've tested my solution on my local setup and solution don't require a lot of RAM memory - about 128MB (tested with process.memory_info().rss), 16MB just for checked_words set (tested with sys.getsizeof()). What could be an issue? How to identify which part of program is causing memory problems?
Your code is too inefficient; there is no need to run a linear loop for every single possible substring to check if it is a palindrome. Since the maximum string length for this problem is only 1000, we can use a simple O(|s|^2) dynamic programming solution that makes use of previous computed results.
Let is_palindrome[l][r]
indicate whether the substring from index l
to r
(inclusive) is a palindrome. First, we initialize this table for all length 1 and 2 palindromes.
For substrings of length at least 3 (r - l > 2
), is_palindrome[l][r]
will be true iff if the characters at index l
and r
match and the substring formed by cutting off one character from each end is also a palindrome (i.e. is_palindrome[i + 1][r - 1]
is true).
class Solution:
def longestPalindrome(self, s: str) -> str:
is_palindrome = [[False] * len(s) for _ in s]
ans = (0,1)
for i in range(len(s)): is_palindrome[i][i] = True
for i in range(len(s) - 1):
if s[i] == s[i + 1]:
is_palindrome[i][i + 1] = True
ans = (i,i+2)
for l in range(3, len(s) + 1):
for i in range(0, len(s) - l + 1):
if s[i] == s[i + l - 1] and is_palindrome[i + 1][i + l - 2]:
is_palindrome[i][i + l - 1] = True
ans = (i,i+l)
return s[slice(*ans)]
Note that there are also solutions that solve this problem in O(|s|) time, but that is not necessary for this question.