{x}
blog image

Unique Paths

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

 

Constraints:

  • 1 <= m, n <= 100

Solution Explanation for Unique Paths

This problem asks to find the number of unique paths a robot can take to reach the bottom-right corner of an m x n grid, starting from the top-left corner. The robot can only move down or right at any point.

Approach 1: Dynamic Programming

This approach uses dynamic programming to solve the problem efficiently. We create a 2D array f where f[i][j] represents the number of unique paths to reach cell (i, j).

State Transition Equation:

The number of paths to reach (i, j) is the sum of paths from the cell above (i-1, j) and the cell to the left (i, j-1):

f[i][j] = f[i-1][j] + f[i][j-1]

Base Cases:

  • f[0][0] = 1 (There's one path to reach the starting cell).
  • f[i][0] = 1 for all i (Only one way to reach any cell in the first column - moving down).
  • f[0][j] = 1 for all j (Only one way to reach any cell in the first row - moving right).

Algorithm:

  1. Initialize a 2D array f of size m x n with all elements set to 0.
  2. Set f[0][0] = 1.
  3. Iterate through the array, calculating f[i][j] using the state transition equation.
  4. The final answer is f[m-1][n-1].

Optimization:

We can optimize space complexity by using a 1D array instead of a 2D array. Since f[i][j] only depends on f[i-1][j] and f[i][j-1], we can update the array in place.

Time Complexity: O(mn) - We iterate through the entire grid once. Space Complexity: O(n) for the optimized 1D array approach; O(mn) for the 2D array approach.

Approach 2 & 3: Further Space Optimization (Variations of DP)

Approach 2 still uses a 2D array but initializes it differently, streamlining the code slightly. Approach 3 optimizes space even further by reducing it to a single 1D array. The core DP logic remains the same, but the array manipulation is more concise.

Code Examples (Optimized 1D array - Approach 3)

Here's the code in several programming languages demonstrating the optimized 1D array approach (Approach 3):

Python:

class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        f = [1] * n
        for i in range(1, m):
            for j in range(1, n):
                f[j] += f[j - 1]
        return f[-1]

Java:

class Solution {
    public int uniquePaths(int m, int n) {
        int[] f = new int[n];
        Arrays.fill(f, 1);
        for (int i = 1; i < m; ++i) {
            for (int j = 1; j < n; ++j) {
                f[j] += f[j - 1];
            }
        }
        return f[n - 1];
    }
}

C++:

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<int> f(n, 1);
        for (int i = 1; i < m; ++i) {
            for (int j = 1; j < n; ++j) {
                f[j] += f[j - 1];
            }
        }
        return f[n - 1];
    }
};

JavaScript:

var uniquePaths = function(m, n) {
    let f = new Array(n).fill(1);
    for (let i = 1; i < m; i++) {
        for (let j = 1; j < n; j++) {
            f[j] += f[j - 1];
        }
    }
    return f[n - 1];
};

The other languages (Go, TypeScript, Rust) would follow a very similar structure to this optimized 1D array approach. The core concept of dynamic programming remains consistent across all implementations.