Python에서 가장 긴 Palindromic Substring에 대한 LeetCode

Nov 01 2020

이것은 LeetCode 의 프로그래밍 질문입니다 .

문자열 s가 주어지면 s에서 가장 긴 회문 부분 문자열을 반환합니다.

예 1 :

입력 : s = "babad"출력 : "bab"참고 : "aba"도 유효한 대답입니다.

아래는 "Time Limit Exceeded"로 인해 다음 입력에 실패한 코드입니다.

""

class Solution(object):

    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        if len(s) == 0:
            return None
        if len(s) == 1:
            return s

        P = [[False]*len(s) for i in range(len(s))]

        for i in range(len(s)):
            P[i][i]   = True

        for i in range(len(s)-1):
            P[i][i+1] = (s[i]==s[i+1])

        for s_len in range(3,len(s)+1):
            for i in range(len(s)+1-s_len):
                P[i][i+s_len-1] = P[i+1][i+s_len-2] and (s[i]==s[i+s_len-1])

        ip = 0
        jp = 0
        max_len = 1

        for i in range(len(s)):
            for j in range(len(s)):
                if P[i][j] and j+1-i > max_len:
                    max_len = j+1-i
                    ip = i
                    jp = j 
                    continue

        return s[ip:jp+1]

사이트 솔루션에 설명 된 다음 접근 방식을 따르려고했습니다. 누구든지 내 코드를 더 효율적으로 만드는 방법을 볼 수 있습니까?


답변

6 Emma Nov 01 2020 at 08:36

면책 조항 : 코드 리뷰어 아님

다음은 몇 가지 간단한 설명입니다.

  • 두 번 반복됩니다.
  • 그것은 무차별 대입이 될 것입니다.
  • Brute Force는 일반적으로 LeetCode에 대한 중간 및 어려운 질문에 실패합니다.

대체 솔루션

  • 여기서 우리는 한 번 반복합니다.
class Solution:
    def longestPalindrome(self, s):
        if len(s) < 1:
            return s

        def isPalindrome(left, right):
            return s[left:right] == s[left:right][::-1]

        left, right = 0, 1
        for index in range(1, len(s)):
            if index - right > 0 and isPalindrome(index - right - 1, index + 1):
                left, right = index - right - 1, right + 2
            if index - right >= 0 and isPalindrome(index - right, index + 1):
                left, right = index - right, right + 1
        return s[left: left + right]

귀하의 솔루션

  • 방금 귀하의 솔루션을 테스트했습니다 (약간 통과).
class Solution(object):

    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        if len(s) < 1:
            return s

        P = [[False] * len(s) for i in range(len(s))]

        for i in range(len(s)):
            P[i][i] = True

        for i in range(len(s) - 1):
            P[i][i + 1] = (s[i] == s[i + 1])

        for s_len in range(3, len(s) + 1):
            for i in range(len(s) + 1 - s_len):
                P[i][i + s_len - 1] = P[i + 1][i + s_len - 2] and (s[i] == s[i + s_len - 1])

        ip = 0
        jp = 0
        max_len = 1

        for i in range(len(s)):
            for j in range(len(s)):
                if P[i][j] and j + 1 - i > max_len:
                    max_len = j + 1 - i
                    ip = i
                    jp = j
                    continue

        return s[ip:jp + 1]

  • 런타임이 높기 때문에 가끔 실패 할 수 있습니다.

  • LeetCode에는 각 문제에 대한 시간 제한이 있다고 생각합니다. 아마도 10 초가이 특정 문제에 대한 제한 일 것입니다.

  • 아마도 지리적 위치 / 시간에 따라 런타임도 다를 것입니다.


좀 더 최적화 :

  • 이 줄을 참조하십시오 for j in range(i + 1, len(s))::
class Solution(object):

    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        if len(s) < 1:
            return s

        P = [[False] * len(s) for _ in range(len(s))]

        for i in range(len(s)):
            P[i][i] = True

        for i in range(len(s) - 1):
            P[i][i + 1] = (s[i] == s[i + 1])

        for s_len in range(3, len(s) + 1):
            for i in range(len(s) + 1 - s_len):
                P[i][i + s_len - 1] = P[i + 1][i + s_len - 2] and (s[i] == s[i + s_len - 1])

        ip = 0
        jp = 0
        max_len = 1

        for i in range(len(s)):
            for j in range(i + 1, len(s)):
                if P[i][j] and j + 1 - i > max_len:
                    max_len = j + 1 - i
                    ip = i
                    jp = j
                    continue

        return s[ip:jp + 1]

  • 약 1 초 감소하지만 여전히 좋지 않습니다.

  • 더 많은 최적화 방법이 있다고 확신합니다.

  • 잠시만 요! 여기에 좋은 파이썬 리뷰어가 있습니다. 아마도 당신을 도울 것입니다.


몇 가지 의견이 있습니다.

class Solution:
    def longestPalindrome(self, s):
        if len(s) < 1:
            return s

        def isPalindrome(left, right):
            return s[left:right] == s[left:right][::-1]

        # We set the left pointer on the first index
        # We set the right pointer on the second index
        # That's the minimum true palindrome
        left, right = 0, 1

        # We visit the alphabets from the second index forward once
        for index in range(1, len(s)):
            # Here we move the right pointer twice and once checking for palindromeness
            # We boundary check using index - right, to remain positive
            if index - right > 0 and isPalindrome(index - right - 1, index + 1):
                print(f"Step {index - 1}: Left pointer is at {index - right - 1} and Right pointer is at {index + 1}")
                print(f"Palindromeness start: {index - right - 1} - Palindromeness end: {index + 1}")
                print(f"Window length: {right}")
                print(f"Before: Left is {left} and Right is {left + right}")
                left, right = index - right - 1, right + 2
                print(f"After: Left is {left} and Right is {left + right}")
                print(f"String: {s[left: left + right]}")
                print('#' * 50)
            if index - right >= 0 and isPalindrome(index - right, index + 1):
                print(f"Step {index - 1}: Left pointer is at {index - right} and Right pointer is at {index + 1}")
                print(f"Palindromeness start: {index - right - 1} - Palindromeness end: {index + 1}")
                print(f"Window length: {right + 1}")
                print(f"Before: Left is {left} and Right is {left + right}")
                left, right = index - right, right + 1
                print(f"After: Left is {left} and Right is {left + right}")
                print(f"String: {s[left: left + right]}")
                print('#' * 50)
        return s[left: left + right]


Solution().longestPalindrome("glwhcebdjbdroiurzfxxrbhzibilmcfasshhtyngwrsnbdpzgjphujzuawbebyhvxfhtoozcitaqibvvowyluvdbvoqikgojxcefzpdgahujuxpiclrrmalncdrotsgkpnfyujgvmhydrzdpiudkfchtklsaprptkzhwxsgafsvkahkbsighlyhjvbburdfjdfvjbaiivqxdqwivsjzztzkzygcsyxlvvwlckbsmvwjvrhvqfewjxgefeowfhrcturolvfgxilqdqvitbcebuooclugypurlsbdfquzsqngbscqwlrdpxeahricvtfqpnrfwbyjvahrtosovsbzhxtutyfjwjbpkfujeoueykmbcjtluuxvmffwgqjgrtsxtdimsescgahnudmsmyfijtfrcbkibbypenxnpiozzrnljazjgrftitldcueswqitrcvjzvlhionutppppzxoepvtzhkzjetpfqsuirdcyqfjsqhdewswldawhdyijhpqtrwgyfmmyhhkrafisicstqxokdmynnnqxaekzcgygsuzfiguujyxowqdfylesbzhnpznayzlinerzdqjrylyfzndgqokovabhzuskwozuxcsmyclvfwkbimhkdmjacesnvorrrvdwcgfewchbsyzrkktsjxgyybgwbvktvxyurufsrdufcunnfswqddukqrxyrueienhccpeuqbkbumlpxnudmwqdkzvsqsozkifpznwapxaxdclxjxuciyulsbxvwdoiolgxkhlrytiwrpvtjdwsssahupoyyjveedgqsthefdyxvjweaimadykubntfqcpbjyqbtnunuxzyytxfedrycsdhkfymaykeubowvkszzwmbbjezrphqildkmllskfawmcohdqalgccffxursvbyikjoglnillapcbcjuhaxukfhalcslemluvornmijbeawxzokgnlzugxkshrpojrwaasgfmjvkghpdyxt")

인쇄물:

Step 18: Left pointer is at 18 and Right pointer is at 20
Palindromeness start: 17 - Palindromeness end: 20
Window length: 2
Before: Left is 0 and Right is 1
After: Left is 18 and Right is 20
String: xx
##################################################
Step 25: Left pointer is at 24 and Right pointer is at 27
Palindromeness start: 23 - Palindromeness end: 27
Window length: 3
Before: Left is 18 and Right is 20
After: Left is 24 and Right is 27
String: ibi
##################################################
Step 462: Left pointer is at 460 and Right pointer is at 464
Palindromeness start: 459 - Palindromeness end: 464
Window length: 4
Before: Left is 24 and Right is 27
After: Left is 460 and Right is 464
String: pppp
##################################################

행복한 코딩! (ˆ_ˆ)