Unique Paths [Medium]

26 Aug 2026, Updated: 24 Sep 2026 4 min read
3
The Unique Paths problem is a classic example of Dynamic Programming. The number of ways to reach a cell depends on the number of ways to reach the cells above and to the left.

Problem

You are given an m x n grid. A robot starts at the top-left corner and needs to reach the bottom-right corner. The robot can move only right or down.

Return the number of unique paths from the starting cell to the destination.

Example(s)

Consider the following example(s) to understand the expected input and output.

Input

m = 3
n = 3

[S] → [ ] → [ ]
 ↓     ↓     ↓
[ ] → [ ] → [ ]
 ↓     ↓     ↓
[ ] → [ ] → [E]

Output

6

Solution

This problem can be solved using Memoization.

The robot starts at the top-left corner (0, 0). From every cell, it has two choices: move down or move right.

From the starting position, we calculate the paths after taking the first move in both possible directions:
Move Right → paths(0, 1) 
Move Down → paths(1, 0)
For every remaining cell, the total number of paths is:
paths(i, j) = paths(i + 1, j) + paths(i, j + 1)
If the robot moves outside the grid, that path is invalid, so we return 0. If the robot reaches the bottom-right corner, it has found one valid path, so we return 1.

The same cell can be reached through multiple paths, so we store its result in a memoization array and reuse it when needed.
class Solution {

    public int uniquePaths(int m, int n) {
        Integer[][] memo = new Integer[m][n];
        return uniquePathsHelper(m, n, 0, 0, memo);
    }

    private int uniquePathsHelper(int m, int n, int i, int j, Integer[][] memo) {
        // Destination reached
        if (i == m - 1 && j == n - 1)
            return 1;

        // Invalid path
        if (i == m || j == n)
            return 0;

        // Return already calculated result
        if (memo[i][j] != null)
            return memo[i][j];

        // Possible moves: down or right
        return memo[i][j] = uniquePathsHelper(m, n, i + 1, j, memo)
                + uniquePathsHelper(m, n, i, j + 1, memo);
    }
}

Complexity

Each cell is calculated only once, resulting in O(m × n) time complexity. The memoization array requires O(m × n) space, and the recursion stack can grow up to O(m + n).

Tabulation Approach

Instead of recursively calculating the number of paths from each cell, we can build the solution using a DP table.

The first row and first column contain only 1 path to every cell because the robot can move only right or down.

For every other cell, the robot can arrive either from the top or from the left. Therefore:
dp[row][col] = dp[row - 1][col] + dp[row][col - 1]
class Solution {
    public int uniquePaths(int m, int n) {
        int[][] dp = new int[m][n];

        // One path to every cell in the first row and column.
        for (int i = 0; i < m; i++) {
            dp[i][0] = 1;
        }

        for (int j = 0; j < n; j++) {
            dp[0][j] = 1;
        }

        // Build the remaining cells.
        for (int row = 1; row < m; row++) {
            for (int col = 1; col < n; col++) {
                dp[row][col] = dp[row - 1][col]
                        + dp[row][col - 1];
            }
        }
        return dp[m - 1][n - 1];
    }
}

Complexity

Each cell is calculated once, resulting in O(m × n) time complexity. The DP table stores m × n values, requiring O(m × n) space.

Space Optimized Approach

In the tabulation approach, each cell depends only on the value above it and the value to its left. Therefore, we do not need to store the entire grid.

We can use a one-dimensional array where dp[col] represents the number of paths to the current cell. As we move row by row, dp[col] already contains the value from the cell above, while dp[col - 1] contains the value from the left.
class Solution {
    public int uniquePaths(int m, int n) {
        int[] dp = new int[n];
        Arrays.fill(dp, 1);

        for (int row = 1; row < m; row++) {
            for (int col = 1; col < n; col++) {
                // Paths from above + paths from the left.
                dp[col] = dp[col] + dp[col - 1];
            }
        }
        return dp[n - 1];
    }
}

Complexity

Each cell is processed once, resulting in O(m × n) time complexity. The one-dimensional DP array requires O(n) space.
Nagesh Chauhan

Nagesh Chauhan

Principal Software Engineer • Java • Python • Distributed Systems • AI/ML

Principal Software Engineer with 14+ years of experience designing and delivering large-scale distributed systems, cloud-native applications, and AI-powered platforms.

Passionate about solving complex engineering problems using strong data structures and algorithms, along with expertise in Java, Spring Boot, Python, System Design, Microservices, Cloud, Kafka, Elasticsearch, and Generative AI.

Share this Article

💬 Comments

Join the Discussion