Level Up Your Coding Skills & Crack Interviews — Save up to 50% or more on Educative.io Today! Claim Discount

Arrow
Table of contents

64. Minimum Path Sum

Problem Statement

You are given an m x n grid of non-negative integers. Starting at the top-left cell (0, 0), you must reach the bottom-right cell (m-1, n-1) by moving only right or down at each step. Your task is to return the minimum possible sum of the values along any valid path, including both the starting and ending cells.

Constraints:

  • m $==$ grid.length
  • n $==$ grid[i].length
  • $1 \leq$ m, n $\leq 200$
  • 0$ \leq$ grid[i][j] $\leq 200$

Examples

InputOutputExplanation
[[2,1,3],[4,0,2],[1,5,1]]6One optimal path is 2 → 1 → 0 → 2 → 1, which totals 6.
[[1,2,1,3],[4,1,0,2]]6Dropping down at the right moment allows using 0, giving total 6.
[[5,1,2],[4,3,1],[2,1,8],[0,2,1]]13The best route avoids the 8 and reaches the end with sum 13.

Why Recursive Approach is Impractical

A path’s sum depends only on the cells you step on, and every move reduces the remaining distance to the goal, so the problem naturally suggests comparing different routes.

A straightforward brute-force idea is: from each cell, recursively try moving right and down, compute the minimum sum to the end, and take the smaller result. This works, but it repeats the same subproblems many times.

This solution has an exponential, roughly $O(2^{m+n})$ time complexity because at most positions you branch into two choices (right/down), generating a huge number of paths. The space complexity of this solution is $O(m+n)$ for recursion depth (the longest path length), ignoring output.

Because this repeated work is the main bottleneck, we switch to a method that reuses results instead of recomputing them.

Optimal Solution using Dynamic Programming

We use the idea that to arrive at the cell (i, j), the previous step must be either from (i-1, j) (from above) or (i, j-1) (from left). If we already know the cheapest cost to reach those neighbors, the cheapest cost to reach (i, j) is just the current cell value plus the smaller of the two neighbor costs. This leads to the standard update: grid[i][j] += min(grid[i-1][j], grid[i][j-1]) once the borders are prepared.

Algorithmic Steps

This algorithm is implemented as follows:

  1. Store the number of rows and columns of the grid in variables m and n respectively.
  2. Iterate through the grid, row by row, using an outer loop over i.
    1. For each row, iterate through its columns using an inner loop over j.
      1. When you are at the starting cell (0, 0),
        1. Leave it unchanged and move to the next iteration.
      2. If the cell is in the first row (i == 0 and j > 0),
        1. It can only be reached from the left, so add the value of the left cell to it.
      3. If the cell is in the first column (j == 0 and i > 0),
        1. It can only be reached from above, so add the value of the above cell to it.
      4. For all other cells,
        1. Take the smaller of the accumulated sums from the top and left neighbors, add it to the current cell.
  3. After filling the grid, return the value in the bottom-right cell, since it represents the minimum path sum to the destination.

The brute-force approach is slow because it repeatedly recomputes the best cost from the same cell. Dynamic programming addresses this issue by storing, for each cell, the minimum path sum required to reach it, ensuring that every cell is solved only once.

Here is a visual representation of the algorithm discussed above:

1 / 10

Python Implementation

Let’s implement the algorithm as discussed above:

Time Complexity

The time complexity of the solution is $O(m⋅n)$ because each cell in the grid is updated exactly once.

Space Complexity

The space complexity of the solution is $O(1)$ because the input grid is reused to store the running minimum sums, and no auxiliary space is used.

Frequently Asked Questions

Why does dynamic programming fit this problem well?

Each cell’s best answer depends only on previously solved neighboring cells (top and left), creating clear overlapping subproblems.

Why are only the top and left neighbors considered in the solution?

In the solution, only the top and left neighbors are considered because the only ways to enter (i, j) are from (i-1, j) (down move) or from (i, j-1) (right move).

Is recursion with memoization acceptable for this problem?

Yes, memoization also runs in O(m · n), but iterative DP avoids recursion depth limits and is often clearer.

What happens if the grid has only one row?

There is only one valid path (all moves right), so the answer is the sum of that row.

What happens if the grid has only one column?

There is only one valid path (all moves down), so the answer is the sum of that column.

Share with others:

Leave a Reply

Your email address will not be published. Required fields are marked *