Introduction
LeetCode 97: Interleaving String is a problem that involves checking whether a string s3
is formed by interleaving two other strings s1
and s2
. The strings s1
and s2
are interleaved in such a way that they maintain their relative order in the interleaved string s3
.
This is a classic example of a dynamic programming problem where you need to determine if it's possible to interleave two strings in such a way that the resultant string has all the characters of both strings while maintaining their order.
Problem Statement
Given strings s1
, s2
, and s3
, return true
if s3
is formed by an interleaving of s1
and s2
, or false
otherwise.
- An interleaving of two strings
s1
and s2
is formed by merging them into a single string in such a way that both strings retain their relative order.
- Note that a string
s3
is considered to be formed by interleaving s1
and s2
if:
s3
contains all characters of s1
and s2
.
- The characters of
s1
and s2
appear in the same order in s3
.
Example:
go
Input: s1 = "abc", s2 = "def", s3 = "adbcef"
Output: true
Explanation: "adbcef" is an interleaving of "abc" and "def".
Input: s1 = "abc", s2 = "def", s3 = "abdecf"
Output: false
Explanation: "abdecf" is not an interleaving of "abc" and "def".
Approach:
Dynamic Programming Approach:
This problem can be solved efficiently using dynamic programming (DP). The idea is to use a 2D DP table to check whether it is possible to interleave s1
and s2
to form s3
.
- Initial Checks:
- First, check if the total length of
s3
is equal to the sum of the lengths of s1
and s2
. If not, return false
immediately.
- If the lengths match, we proceed to create the DP table.
- Dynamic Programming Table:
- We define a 2D DP table
dp[i][j]
where:
dp[i][j]
is true
if the first i
characters of s1
and the first j
characters of s2
can form the first i + j
characters of s3
.
- The state transition is based on whether the characters of
s1
or s2
match the corresponding characters in s3
.
- Base Case:
- If both
s1
and s2
are empty, then s3
must also be empty, and the result is true
.
- Recursive Formula:
- If the character from
s1
matches the current character in s3
, we can inherit the solution from dp[i-1][j]
.
- If the character from
s2
matches the current character in s3
, we can inherit the solution from dp[i][j-1]
.
- Final Result:
- The final result is found in
dp[len(s1)][len(s2)]
, which tells us whether we can interleave the entire s1
and s2
to form s3
.
Go Implementation
Dynamic Programming Solution
go
func isInterleave(s1 string, s2 string, s3 string) bool {
// If the total length of s1 and s2 doesn't match the length of s3, return false
if len(s1)+len(s2) != len(s3) {
return false
}
// Initialize a 2D DP table with dimensions (len(s1)+1) x (len(s2)+1)
dp := make([][]bool, len(s1)+1)
for i := range dp {
dp[i] = make([]bool, len(s2)+1)
}
// Initialize the base case
dp[0][0] = true
// Fill the DP table
for i := 0; i <= len(s1); i++ {
for j := 0; j <= len(s2); j++ {
// Check if we can take a character from s1
if i > 0 && s1[i-1] == s3[i+j-1] {
dp[i][j] = dp[i][j] || dp[i-1][j]
}
// Check if we can take a character from s2
if j > 0 && s2[j-1] == s3[i+j-1] {
dp[i][j] = dp[i][j] || dp[i][j-1]
}
}
}
// The result is in dp[len(s1)][len(s2)]
return dp[len(s1)][len(s2)]
}
Explanation:
- Input and Base Case:
- First, we check if the lengths of
s1
and s2
combined equal the length of s3
. If they don't, we return false
early because it's impossible for s3
to be an interleaving of s1
and s2
.
- Dynamic Programming Table:
- We create a 2D boolean array
dp
where each cell dp[i][j]
represents whether the first i
characters of s1
and the first j
characters of s2
can form the first i + j
characters of s3
.
- Filling the DP Table:
- We iterate over all possible lengths
i
and j
for the two strings.
- For each combination of
i
and j
, we check if:
- The character from
s1[i-1]
matches s3[i+j-1]
and if the previous state dp[i-1][j]
is true
.
- The character from
s2[j-1]
matches s3[i+j-1]
and if the previous state dp[i][j-1]
is true
.
- Result:
- The final result is found in
dp[len(s1)][len(s2)]
, which tells us whether we can interleave s1
and s2
to form s3
.
Time and Space Complexity
MetricComplexityTime ComplexityO(m * n)Space ComplexityO(m * n)
Where:
m
is the length of s1
, and n
is the length of s2
.
- Time Complexity: We need to fill a DP table of size
(m+1) x (n+1)
, leading to a time complexity of O(m * n).
- Space Complexity: The space complexity is O(m * n) due to the storage required for the DP table.
Edge Cases
- Empty Strings:
- Input:
s1 = ""
, s2 = ""
, s3 = ""
- Output:
true
- Explanation: An empty
s3
is a valid interleaving of two empty strings.
- Length Mismatch:
- Input:
s1 = "abc"
, s2 = "def"
, s3 = "abdef"
- Output:
false
- Explanation: The length of
s3
must be the sum of the lengths of s1
and s2
, so this input is invalid.
- One String is Empty:
- Input:
s1 = "abc"
, s2 = ""
, s3 = "abc"
- Output:
true
- Explanation: If one string is empty,
s3
should match the non-empty string exactly.
Conclusion
LeetCode 97: Interleaving String is a great problem for practicing dynamic programming. By breaking down the problem into smaller subproblems and using a 2D DP table, we can efficiently check if a string can be interleaved from two other strings. This approach ensures that we explore all possible interleavings without redundant calculations.
The solution has a time complexity of O(m * n) and space complexity of O(m * n), making it an optimal approach for this problem.