You are given a grid of non-negative integers, where each cell represents a cost to traverse that cell. The grid has m
rows and n
columns. Your task is to find the minimum cost path from the top-left cell (0, 0) to the bottom-right cell (m-1, n-1). You can only move down or right at any point in time.
minPathSum(grid)
that takes a 2D array grid
as input and returns the minimum path sum.Example 1:
Input: grid = [[1,3,1],[1,5,1],[4,2,1]]
Output: 7
Explanation: The path 1 -> 3 -> 1 -> 1 -> 1 minimizes the sum.
Example 2:
Input: grid = [[1,2,3],[4,5,6]]
Output: 12
Your solution should be efficient, and you should clearly explain its time and space complexity. Can you optimize the space complexity further?
Given a m x n
grid filled with non-negative numbers, find a path from top left to bottom right, which minimizes the sum of all numbers along its path. You can only move either down or right at any point in time.
The brute force solution would involve exploring every possible path from the top-left corner to the bottom-right corner. This can be done recursively. At each cell, we have two choices: move down or move right. We explore both possibilities and return the minimum sum among all paths.
def min_path_sum_brute_force(grid):
def solve(row, col):
if row == len(grid) - 1 and col == len(grid[0]) - 1:
return grid[row][col]
if row >= len(grid) or col >= len(grid[0]):
return float('inf')
return grid[row][col] + min(solve(row + 1, col), solve(row, col + 1))
return solve(0, 0)
The time complexity is exponential, O(2^(m+n)), because in the worst case, we explore every possible path.
The space complexity is O(m+n) due to the depth of the recursion stack.
Dynamic programming can be used to solve this problem efficiently. We can create a DP table dp
of the same dimensions as the input grid. dp[i][j]
will store the minimum path sum from the top-left corner to cell (i, j)
. We can populate the dp
table as follows:
dp[0][0]
with grid[0][0]
.dp[0][j] = dp[0][j-1] + grid[0][j]
.dp[i][0] = dp[i-1][0] + grid[i][0]
.dp[i][j] = grid[i][j] + min(dp[i-1][j], dp[i][j-1])
.Finally, dp[m-1][n-1]
will contain the minimum path sum from the top-left to the bottom-right.
def min_path_sum_dp(grid):
m = len(grid)
n = len(grid[0])
dp = [[0] * n for _ in range(m)]
dp[0][0] = grid[0][0]
for i in range(1, m):
dp[i][0] = dp[i-1][0] + grid[i][0]
for j in range(1, n):
dp[0][j] = dp[0][j-1] + grid[0][j]
for i in range(1, m):
for j in range(1, n):
dp[i][j] = grid[i][j] + min(dp[i-1][j], dp[i][j-1])
return dp[m-1][n-1]
The time complexity is O(m*n) because we iterate through each cell in the grid once.
The space complexity is O(m*n) because we use a DP table of the same dimensions as the grid.
We can optimize the space complexity to O(n) by using only one row to store the DP values. We iterate over the rows and update the current row based on the previous row.
def min_path_sum_dp_optimized(grid):
m = len(grid)
n = len(grid[0])
dp = [0] * n
for i in range(m):
for j in range(n):
if i == 0 and j == 0:
dp[j] = grid[i][j]
elif i == 0:
dp[j] = dp[j-1] + grid[i][j]
elif j == 0:
dp[j] = dp[j] + grid[i][j]
else:
dp[j] = grid[i][j] + min(dp[j-1], dp[j])
return dp[n-1]
The time complexity remains O(m*n), but the space complexity is now O(n).