There is a robot on an m x n
grid. The robot is initially located at the top-left corner (i.e., grid[0][0]
). The robot tries to move to the bottom-right corner (i.e., grid[m - 1][n - 1]
). The robot can only move either down or right at any point in time.
Given the two integers m
and n
, return the number of possible unique paths that the robot can take to reach the bottom-right corner.
The test cases are generated so that the answer will be less than or equal to 2 * 109
.
Example 1:
Input: m = 3, n = 7
Output: 28
Example 2:
Input: m = 3, n = 2
Output: 3
Explanation: From the top-left corner, there are a total of 3 ways to reach the bottom-right corner:
1. Right -> Down -> Down
2. Down -> Down -> Right
3. Down -> Right -> Down
To solve this problem, I've used dynamic programming (DP). The idea is to break down the problem into smaller subproblems and solve them. We create a DP array where each element dp[i][j]
represents the number of unique paths to reach the cell (i, j)
from the top-left corner.
You're right. The initialization should indeed refer to the last row, given that the solution is implemented in a bottom-up way. Let's correct that and provide the detailed explanation accordingly.
-
Initialization:
- Initialize a 1D DP array
row
of sizen
with all elements set to 1. This array represents the number of ways to reach each cell in the last row, which is always 1 because there is only one way to move right to reach any cell in the last row.
- Initialize a 1D DP array
-
Filling the DP Table:
- Iterate over the rows of the grid starting from the second last row up to the first row.
- For each row, create a new DP array
newRow
of sizen
initialized to 1. - Iterate over the columns of the current row from right to left. For each cell
(i, j)
, updatenewRow[j]
to be the sum ofnewRow[j+1]
(number of ways to reach the cell to the right) androw[j]
(number of ways to reach the cell below). - Update
row
to benewRow
after processing each row.
-
Result:
- The answer is found in
row[0]
, which represents the number of unique paths to reach the bottom-right corner from the top-left corner.
- The answer is found in
Let's walk through the example m = 3
, n = 7
:
-
Initialization:
row = [1, 1, 1, 1, 1, 1, 1]
-
Iteration:
- For the first row iteration (
i = 1
):newRow = [1, 1, 1, 1, 1, 1, 1]
- For
j = 5
to0
:newRow[5] = newRow[6] + row[5] = 1 + 1 = 2
newRow[4] = newRow[5] + row[4] = 2 + 1 = 3
newRow[3] = newRow[4] + row[3] = 3 + 1 = 4
newRow[2] = newRow[3] + row[2] = 4 + 1 = 5
newRow[1] = newRow[2] + row[1] = 5 + 1 = 6
newRow[0] = newRow[1] + row[0] = 6 + 1 = 7
- Update
row
tonewRow
- For the second row iteration (
i = 0
):newRow = [1, 1, 1, 1, 1, 1, 1]
- For
j = 5
to0
:newRow[5] = newRow[6] + row[5] = 1 + 2 = 3
newRow[4] = newRow[5] + row[4] = 3 + 3 = 6
newRow[3] = newRow[4] + row[3] = 6 + 4 = 10
newRow[2] = newRow[3] + row[2] = 10 + 5 = 15
newRow[1] = newRow[2] + row[1] = 15 + 6 = 21
newRow[0] = newRow[1] + row[0] = 21 + 7 = 28
- Update
row
tonewRow
- For the first row iteration (
-
Result:
- The final
row
is[28, 21, 15, 10, 6, 3, 1]
row[0]
is28
, which is the number of unique paths from the top-left to the bottom-right corner.
- The final
-
Time Complexity:
$O(m \cdot n)$ , wherem
is the number of rows andn
is the number of columns. We iterate through each cell of the grid once. -
Space Complexity:
$O(n)$ , wheren
is the number of columns. We use a 1D DP array of sizen
to store the number of unique paths.
Given two strings text1
and text2
, return the length of their longest common subsequence. If there is no common subsequence, return 0
.
A subsequence of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters.
- For example,
"ace"
is a subsequence of"abcde"
.
A common subsequence of two strings is a subsequence that is common to both strings.
Example 1:
Example matrix
[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]
Input: text1 = "abcde", text2 = "ace"
Output: 3
Explanation: The longest common subsequence is "ace" and its length is 3.
Example 2:
Input: text1 = "abc", text2 = "abc"
Output: 3
Explanation: The longest common subsequence is "abc" and its length is 3.
Example 3:
Input: text1 = "abc", text2 = "def"
Output: 0
Explanation: There is no such common subsequence, so the result is 0.
This problem can be solved using dynamic programming. The idea is to create a 2D table dp
where dp[i][j]
represents the length of the longest common subsequence of the substrings text1[0:i]
and text2[0:j]
.
-
DP Table Initialization:
- We initialize a 2D list
dp
with dimensions(len(text1) + 1) x (len(text2) + 1)
filled with 0s. This table will help us store the lengths of LCS for substrings oftext1
andtext2
. - The extra row and column are to handle the case when either string is empty, in which case the LCS length is 0.
- We initialize a 2D list
-
Filling the DP Table:
- We start filling the table from the bottom-right corner.
- For each pair of indices
i
andj
, if the characterstext1[i]
andtext2[j]
match, thendp[i][j]
is1 + dp[i + 1][j + 1]
, because the current character can be included in the LCS. - If the characters don't match, we take the maximum value between
dp[i + 1][j]
anddp[i][j + 1]
, which represents skipping one of the characters in eithertext1
ortext2
.
-
Result:
- After filling the table, the top-left corner
dp[0][0]
contains the length of the longest common subsequence of the two strings.
- After filling the table, the top-left corner
Let's go through the example "abcde"
and "ace"
in detail to understand how we can find the length of the longest common subsequence (LCS) step by step.
-
Iteration 1:
-
Start with
i = 4
andj = 2
(Comparingtext1[4] = "e"
withtext2[2] = "e"
) -
The characters match (
"e" == "e"
). -
Update
dp[4][2] = 1 + dp[5][3] = 1 + 0 = 1
. -
The updated
dp
table:dp = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 0]]
-
-
Iteration 2:
-
We move to
i = 4
andj = 1
(comparingtext1[4] = "e"
withtext2[1] = "c"
). -
The characters do not match (
"e" != "c"
), so we cannot include this character in our common subsequence. -
To decide the value of
dp[4][1]
, we look at the right celldp[4][2]
and the cell belowdp[5][1]
.dp[4][2]
gives us the LCS length if we skip the current character intext2
.dp[5][1]
gives us the LCS length if we skip the current character intext1
.
-
We take the maximum of these two values:
dp[4][1] = max(dp[4][2], dp[5][1]) = max(1, 0) = 1
. -
This means that up to this point, the maximum LCS length considering these two characters remains 1.
-
The updated
dp
table is:dp = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 1, 1, 0], [0, 0, 0, 0]]
-
-
Iteration 3:
-
Move to
i = 4
andj = 0
(Comparingtext1[4] = "e"
withtext2[0] = "a"
) -
The characters do not match (
"e" != "a"
). -
Update
dp[4][0] = max(dp[4][1], dp[5][0]) = max(1, 0) = 1
. -
The updated
dp
table:dp = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [1, 1, 1, 0], [0, 0, 0, 0]]
-
-
Iteration 4:
-
Move to
i = 3
andj = 2
(Comparingtext1[3] = "d"
withtext2[2] = "e"
) -
The characters do not match (
"d" != "e"
). -
Update
dp[3][2] = max(dp[3][3], dp[4][2]) = max(0, 1) = 1
. -
The updated
dp
table:dp = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 0], [1, 1, 1, 0], [0, 0, 0, 0]]
-
-
Iteration 5:
-
Move to
i = 3
andj = 1
(Comparingtext1[3] = "d"
withtext2[1] = "c"
) -
The characters do not match (
"d" != "c"
). -
Update
dp[3][1] = max(dp[3][2], dp[4][1]) = max(1, 1) = 1
. -
The updated
dp
table:dp = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 1, 1, 0], [1, 1, 1, 0], [0, 0, 0, 0]]
-
-
Iteration 6:
-
Move to
i = 3
andj = 0
(Comparingtext1[3] = "d"
withtext2[0] = "a"
) -
The characters do not match (
"d" != "a"
). -
Update
dp[3][0] = max(dp[3][1], dp[4][0]) = max(1, 1) = 1
. -
The updated
dp
table:dp = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [1, 1, 1, 0], [1, 1, 1, 0], [0, 0, 0, 0]]
-
-
Iteration 7:
-
Move to
i = 2
andj = 2
(Comparingtext1[2] = "c"
withtext2[2] = "e"
) -
The characters do not match (
"c" != "e"
). -
Update
dp[2][2] = max(dp[2][3], dp[3][2]) = max(0, 1) = 1
. -
The updated
dp
table:dp = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [0, 0, 0, 0]]
-
-
Iteration 8:
-
Move to
i = 2
andj = 1
(Comparingtext1[2] = "c"
withtext2[1] = "c"
) -
The characters match (
"c" == "c"
). -
Update
dp[2][1] = 1 + dp[3][2] = 1 + 1 = 2
. -
The updated
dp
table:dp = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 2, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [0, 0, 0, 0]]
-
-
Iteration 9:
-
Move to
i = 2
andj = 0
(Comparingtext1[2] = "c"
withtext2[0] = "a"
) -
The characters do not match (
"c" != "a"
). -
Update
dp[2][0] = max(dp[2][1], dp[3][0]) = max(2, 1) = 2
. -
The updated
dp
table:dp = [[0, 0, 0, 0], [0, 0, 0, 0], [2, 2, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [0, 0, 0, 0]]
-
-
Iteration 10:
-
Move to
i = 1
andj = 2
(Comparingtext1[1] = "b"
withtext2[2] = "e"
) -
The characters do not match (
"b" != "e"
). -
Update
dp[1][2] = max(dp[1][3], dp[2][2]) = max(0, 1) = 1
. -
The updated
dp
table:dp = [[0, 0, 0, 0], [0, 0, 1, 0], [2, 2, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [0, 0, 0, 0]]
-
-
Iteration 11:
-
Move to
i = 1
andj = 1
(Comparingtext1[1] = "b"
withtext2[1] = "c"
) -
The characters do not match (
"b" != "c"
). -
Update
dp[1][1] = max(dp[1][2], dp[2][1]) = max(1, 2) = 2
. -
The updated
dp
table:dp = [[0, 0, 0, 0], [0, 2, 1, 0], [2, 2, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [0, 0, 0, 0]]
-
-
Iteration 12:
-
Move to
i = 1
andj = 0
(Comparingtext1[1] = "b"
withtext2[0] = "a"
) -
The characters do not match (
"b" != "a"
). -
Update
dp[1][0] = max(dp[1][1], dp[2][0]) = max(2, 2) = 2
. -
The updated
dp
table:dp = [[0, 0, 0, 0], [2, 2, 1, 0], [2, 2, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [0, 0, 0, 0]]
-
-
Iteration 13:
-
Move to
i = 0
andj = 2
(Comparingtext1[0] = "a"
withtext2[2] = "e"
) -
The characters do not match (
"a" != "e"
). -
Update
dp[0][2] = max(dp[0][3], dp[1][2]) = max(0, 1) = 1
. -
The updated
dp
table:dp = [[0, 0, 1, 0], [2, 2, 1, 0], [2, 2, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [0, 0, 0, 0]]
-
-
Iteration 14:
-
Move to
i = 0
andj = 1
(Comparingtext1[0] = "a"
withtext2[1] = "c"
) -
The characters do not match (
"a" != "c"
). -
Update
dp[0][1] = max(dp[0][2], dp[1][1]) = max(1, 2) = 2
. -
The updated
dp
table:dp = [[0, 2, 1, 0], [2, 2, 1, 0], [2, 2, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [0, 0, 0, 0]]
-
-
Iteration 15:
-
Move to
i = 0
andj = 0
(Comparingtext1[0] = "a"
withtext2[0] = "a"
) -
The characters match (
"a" == "a"
). -
Update
dp[0][0] = 1 + dp[1][1] = 1 + 2 = 3
. -
The final
dp
table:dp = [[3, 2, 1, 0], [2, 2, 1, 0], [2, 2, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [0, 0, 0, 0]]
-
- The value at
dp[0][0]
is3
, which is the length of the longest common subsequence betweentext1 = "abcde"
andtext2 = "ace"
.
-
Time Complexity:
$O(m \times n)$ , wherem
is the length oftext1
andn
is the length oftext2
.- We need to fill a 2D table of size
m x n
.
- We need to fill a 2D table of size
-
Space Complexity:
$O(m \times n)$ .- We use a 2D table to store the lengths of the longest common subsequence for each pair of indices.