1. 程式人生 > >lintcode 29. Interleaving String

lintcode 29. Interleaving String

29. Interleaving String

Given three strings: s1s2s3, determine whether s3 is formed by the interleaving of s1 and s2.

Example

For s1 = "aabcc", s2 = "dbbca"

  • When s3 = "aadbbcbcac", return true.
  • When s3 = "aadbbbaccc", return false.

Challenge

O(n2) time or better

Code

法一:(遞迴)

class Solution:
    """
    @param s1: A string
    @param s2: A string
    @param s3: A string
    @return: Determine whether s3 is formed by interleaving of s1 and s2
    """
    def isInterleave(self, s1, s2, s3):
        # write your code here
        if s1 is None or s2 is None or s3 is None:
            return False
        if len(s1) + len(s2) != len(s3):
            return False
        
        interleave = [[False]*(len(s2)+1) for i in range(len(s1)+1)]
        interleave [0][0] = True
        for i in range(len(s1)):
            interleave[i+1][0] = s1[:i+1] == s3[:i+1]
        for j in range(len(s2)):
            interleave[0][i+1] = s2[:i+1] == s3[:i+1]
        
        for i in range(len(s1)):
            for j in range(len(s2)):
                interleave[i+1][j+1] = False
                if s1[i]==s3[i+j+1]:
                    interleave[i+1][j+1] = interleave[i][j+1]
                if s2[j] == s3[i+j+1]:
                    interleave[i+1][j+1] = interleave[i+1][j]
        return interleave[len(s1)][len(s2)]
class Solution:
    """
    @param s1: A string
    @param s2: A string
    @param s3: A string
    @return: Determine whether s3 is formed by interleaving of s1 and s2
    """
    def isInterleave(self, s1, s2, s3):
        # write your code here
        
        return self._isInterleave(s3, 0, s1, 0, s2, 0)
        
    def _isInterleave(self, s3, s3_start, s1, s1_start, s2, s2_start):
        if (s3_start == len(s3)) and (s1_start == len(s1)) and (s2_start == len(s2)):
            return True
        if (s1_start < len(s1)) and (s3[s3_start] == s1[s1_start]):
            if self._isInterleave(s3, s3_start + 1, s1, s1_start + 1, s2, s2_start):
                return True
        if (s2_start < len(s2)) and (s3[s3_start] == s2[s2_start]):
            if self._isInterleave(s3, s3_start + 1, s1, s1_start, s2, s2_start + 1):
                return True
        return False

法二 :(非遞迴)從s1和s2入手:求s1和s2的組合,太暴力。那就s3入手,第一反應就是對於s3中的每個字母肯定不是在s1就是在s2當中,那麼用一個for或while迴圈遍歷s3,每次迴圈判斷當前字母是否在s1或者s2當中,兩者都沒有就肯定不是“交叉字串”,返回False;如果迴圈結束就返回True。發現每次迴圈中我都是先判斷s1中有沒有元素匹配,如果s2當中也有匹配元素呢,在else當中,不應該直接返回False,而應該回溯,回溯到一開始上一次匹配的地方,即s1[i]==s3[k]相等的地方,不過這次不能拿s1和s3比,而應該拿s2和s3比。

class Solution:
    """
    @param s1: A string
    @param s2: A string
    @param s3: A string
    @return: Determine whether s3 is formed by interleaving of s1 and s2
    """
    def isInterleave(self, s1, s2, s3):
        # write your code here
        i = 0
        j = 0
        k = 0
        # 標記與s1還是s2比較
        flag = 0
        while k < len(s3):
            if i < len(s1) and s3[k] == s1[i] and flag==0:
                i += 1
                k += 1
            elif j < len(s2) and s3[k] == s2[j]:
                j += 1
                k += 1
                flag = 0
            # 回溯
            else:
                i = i-1
                if i <= 0:
                    return False
                k = k - 1
                # 與s2比較
                flag = 1
                
        return True