코딩 테스트 및 알고리즘/leetcode for google

leetcode medium : Interleaving String

띠리링구 2022. 5. 14. 11:04

Interleaving String - LeetCode

 

Interleaving String - LeetCode

Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.

leetcode.com

 

딱~! 봐도 dp문제 ㅋㅋㅋㅋㅋ

 

일단 전체탐색으로 코딩

class Solution:
    def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
        def search(i1, i2):
            i3 = i1 + i2

            if i3 == len(s3):
                return i1 == len(s1) and i2 == len(s2)
            
            b1 = b2 = False
            
            if i1 < len(s1) and s3[i3] == s1[i1]:
                b1 = search(i1 + 1, i2)
                
            if i2 < len(s2) and s3[i3] == s2[i2]:
                b2 = search(i1, i2 + 1)
                
            return b1 or b2
        
        return search(0, 0)

 

memoization 더하면 바로 dp가 됨

class Solution:
    def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
        dp = [[None] * (len(s2) + 1) for _ in range(len(s1) + 1)]
        
        def search(i1, i2):
            i3 = i1 + i2
            
            if dp[i1][i2] != None:
                return dp[i1][i2]
            
            if i3 == len(s3):
                return i1 == len(s1) and i2 == len(s2)
            
            
            b1 = b2 = False


            if i1 < len(s1) and s3[i3] == s1[i1]:
                dp[i1 + 1][i2] = b1 = search(i1 + 1, i2)
                
            if i2 < len(s2) and s3[i3] == s2[i2]:
                dp[i1][i2 + 1] = b2 = search(i1, i2 + 1)
            return b1 or b2
        
        return search(0, 0)

 

근데 문제에 추가조건이 있다.. space complexity를 O( len(s1) * len(s2) )가 아닌 O(len(s2))로 줄여라..!

오 첨엔 어려울거라 생각했는데 생각해보니 당연히 O(len(s2))로 풀수가 있다.

만약 dp[s2]가 True이면 len(s1) + len(s2) == len(s3)이기만 하면 s3는 interleaving of s1 and s2가 될 수밖에 없다.

아 근데 어떻게 짜야될지 모르겠네...;;

 

아 진짜 어렵다;;

 

ㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏ진짬ㄴ이ㅏ럼닏하ㅓㅁ니ㅏㄷㅇ럼니ㅏㅇ럼ㅈ디ㅏㄹ

모르겠다..

 

 

다른 사람들 솔루션을 보자

 

나랑 같은 알고리즘의 top down solution

class Solution:
    def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
        if len(s1) + len(s2) != len(s3): return False
        m, n = len(s1), len(s2)
        
        @lru_cache(None)
        def dp(i, j):
            if i == m and j == n: return True  # Found a valid match
            ans = False
            if i < m and s1[i] == s3[i+j]:  # Case match s1[i] with s3[i+j]
                ans |= dp(i + 1, j)
            if j < n and s2[j] == s3[i+j]:  # Case match s2[j] with s3[i+j]
                ans |= dp(i, j + 1)
            return ans

        return dp(0, 0)

 

bottom-up으로 변환한거

class Solution:
    def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
        if len(s1) + len(s2) != len(s3): return False

        m, n = len(s1), len(s2)
        dp = [[False] * (n + 1) for _ in range(m + 1)]
        dp[m][n] = True
        for i in range(m, -1, -1):
            for j in range(n, -1, -1):
                if i < m and s1[i] == s3[i + j]:
                    dp[i][j] |= dp[i + 1][j]
                if j < n and s2[j] == s3[i + j]:
                    dp[i][j] |= dp[i][j + 1]
        return dp[0][0]

 

공간 최적화된 버전

class Solution:
    def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
        if len(s1) + len(s2) != len(s3): return False

        m, n = len(s1), len(s2)
        dp, dpPrev = [False] * (n + 1), [False] * (n + 1)
        for i in range(m, -1, -1):
            for j in range(n, -1, -1):
                dp[j] = False
                if i == m and j == n:
                    dp[n] = True
                if i < m and s1[i] == s3[i + j]:
                    dp[j] |= dpPrev[j]
                if j < n and s2[j] == s3[i + j]:
                    dp[j] |= dp[j + 1]
            dp, dpPrev = dpPrev, dp
        return dpPrev[0]

 

ㅇㅇ 봐도 모르겠다 ㅋㅋㅋㅋㅋ