97. Interleaving String

Description

Given strings s1, s2, and s3, find whether s3 is formed by an interleaving of s1 and s2.

An interleaving of two strings s and t is a configuration where they are divided into non-empty substrings such that:

  • s = s1 + s2 + ... + sn

  • t = t1 + t2 + ... + tm

  • |n - m| <= 1

  • The interleaving is s1 + t1 + s2 + t2 + s3 + t3 + ... or t1 + s1 + t2 + s2 + t3 + s3 + ...

Note: a + b is the concatenation of strings a and b.

Example 1:

Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
Output: true

Example 2:

Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
Output: false

Example 3:

Input: s1 = "", s2 = "", s3 = ""
Output: true

Constraints:

  • 0 <= s1.length, s2.length <= 100

  • 0 <= s3.length <= 200

  • s1, s2, and s3 consist of lowercase English letters.

Follow up: Could you solve it using only O(s2.length) additional memory space?

Tags

String, Dynamic Programming

Solution

We use a 2D array dp where dp[i][j] represents if s3[:i+j] is formed by an interleaving of s1[:i] and s2[:j].

Edge cases:

  • Return false if len(s1)+len(s2) != len(s3);

  • dp[0][0] = true since "" + "" == "".

In terms of s1, dp[i][j] = true if s1[i] == s3[i+j] and s3[:i-1+j] is formed by an interleaving of s1[:i-1] and s2[:j]. This is also similar to s2. Thus, we can derive a function from it:

f(i,j)=[f(i1,j)&&s1(i1)=s3(i+j1)][f(i,j1)&&s2(j1)=s3(i+j1)]f(i,j)=[f(i−1,j)\&\&s1(i−1)=s3(i+j-1)]\|[f(i,j−1)\&\&s2(j−1)=s3(i+j-1)]

At last, we return dp[len(s1)][len(s2)].

Now that we can observe that dp[i] only depends on dp[i-1], we can compress the len(s1)*len(s2) array to an 1D array with length of len(s2). See Code for details.

Complexity

  • Time complexity: O(mn)O(mn), m and n are the length of s1 and s2, respectively;

  • Space complexity: O(n)O(n)

Code

func isInterleave(s1 string, s2 string, s3 string) bool {
	if len(s1)+len(s2) != len(s3) {
		return false
	}
	dp := make([]bool, len(s2)+1)
	dp[0] = true
	for i := 0; i <= len(s1); i++ {
		for j := 0; j <= len(s2); j++ {
			p := i + j - 1
			if i > 0 {
				dp[j] = dp[j] && s1[i-1] == s3[p] // dp[i][j] = dp[i-1][j] || s1[i-1] == s3[p]
			}
			if j > 0 {
				dp[j] = dp[j] || dp[j-1] && s2[j-1] == s3[p] // dp[i][j] = dp[i][j-1] || s2[j-1] == s3[p]
			}
		}
	}
	return dp[len(s2)]
}

Reference

Last updated

Was this helpful?