3148. Maximum Difference Score in a Grid
Problem Description
You are given an m x n
matrix grid
consisting of positive integers. You can move from a cell in the matrix to any other cell that is either to the bottom or to the right (not necessarily adjacent). The score of a move from a cell with the value c1
to a cell with the value c2
is c2 - c1
.
You can start at any cell, and you have to make at least one move.
Return the maximum total score you can achieve.
Intuition
To solve this problem, we need to explore moving from one cell to another in the matrix while maximizing the score. The score of moving is defined as the difference between the value of the destination cell and the departure cell, c2 - c1
.
We can define a path's score as the final cell value minus the starting cell value. Given this transformation, we aim to maximize the difference between the largest ending cell value and the smallest beginning cell value that can be reached as part of a valid path moving only down or to the right.
Breaking it down, we need to:
- Determine the smallest starting point value for paths ending at each cell
(i, j)
. - Keep track of this minimum value as we iterate through the matrix.
This can be done using dynamic programming. We'll maintain a 2D array f
where f[i][j]
stores the smallest starting point value for paths reaching cell (i, j)
. The dynamic programming transition will involve:
- Considering the path value coming from either the top cell
(i-1, j)
or the left cell(i, j-1)
while including the current cell's valuegrid[i][j]
. - Calculating the score as
grid[i][j] - f[i][j]
and maintaining the maximum score found.
The solution's crucial part is efficiently updating f[i][j]
and the maximum score as we progress through the matrix.
Learn more about Dynamic Programming patterns.
Solution Approach
To implement the solution for this problem, we utilize a dynamic programming approach.
Dynamic Programming
The idea is to traverse through the matrix grid
while keeping track of the minimum starting point for any path ending at each cell (i, j)
. We define a 2-dimensional list f
where f[i][j]
will hold this minimum starting cell value.
Here is a breakdown of the implementation:
-
Initialization:
- Initialize
f
as a matrix of the same dimensions asgrid
with all values set to zero. - Set
ans
to a very low value (negative infinity) which will eventually hold the maximum score.
- Initialize
-
Traversal and State Transition:
- Traverse each cell
(i, j)
in thegrid
. - For each cell, calculate the minimum starting point of the path that can end at
(i, j)
. - This minimum value can come from the top (
f[i-1][j]
) or the left (f[i][j-1]
) of the current cell. It is calculated as:
f[i][j] = min(f[i-1][j], f[i][j-1], grid[i][j])
- Traverse each cell
-
Score Calculation:
- Calculate the possible score for ending a path on cell
(i, j)
asgrid[i][j] - f[i][j]
. - If this score is greater than the current
ans
, updateans
.
- Calculate the possible score for ending a path on cell
-
Return the Result:
- After completing the traversal of the matrix,
ans
will contain the maximum score achievable, which we return.
- After completing the traversal of the matrix,
This approach effectively tracks the potential starting point for any given endpoint, ensuring optimal scores for moves across the matrix.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's consider a small example matrix grid
:
grid = [ [3, 5, 7], [1, 4, 6], [2, 8, 9] ]
We are applying a dynamic programming approach to find the maximum score possible.
-
Initialization:
-
Create a matrix
f
with the same dimensions asgrid
initialized to store minimum starting values:f = [ [0, 0, 0], [0, 0, 0], [0, 0, 0] ]
-
Set
ans
to negative infinity.
-
-
Traversal and State Transition:
-
Start with the first row:
f[0][0]
=grid[0][0]
= 3- Calculate the score for
grid[0][1]
:f[0][1] = min(grid[0][0], grid[0][1]) = min(3, 5) = 3 score = grid[0][1] - f[0][1] = 5 - 3 = 2 ans = max(ans, score) = max(-inf, 2) = 2
- Calculate score for
grid[0][2]
:f[0][2] = min(grid[0][1], grid[0][2]) = min(3, 7) = 3 score = grid[0][2] - f[0][2] = 7 - 3 = 4 ans = max(ans, 4) = 4
-
Move to the second row:
f[1][0] = min(grid[0][0], grid[1][0]) = min(3, 1) = 1
- Calculate score for
grid[1][1]
:f[1][1] = min(f[0][1], f[1][0], grid[1][1]) = min(3, 1, 4) = 1 score = grid[1][1] - f[1][1] = 4 - 1 = 3 ans = max(ans, 3) = 4
- Calculate score for
grid[1][2]
:f[1][2] = min(f[0][2], f[1][1], grid[1][2]) = min(3, 1, 6) = 1 score = grid[1][2] - f[1][2] = 6 - 1 = 5 ans = max(ans, 5) = 5
-
Move to the third row:
f[2][0] = min(f[1][0], grid[2][0]) = min(1, 2) = 1
- Calculate score for
grid[2][1]
:f[2][1] = min(f[1][1], f[2][0], grid[2][1]) = min(1, 1, 8) = 1 score = grid[2][1] - f[2][1] = 8 - 1 = 7 ans = max(ans, 7) = 7
- Calculate score for
grid[2][2]
:f[2][2] = min(f[1][2], f[2][1], grid[2][2]) = min(1, 1, 9) = 1 score = grid[2][2] - f[2][2] = 9 - 1 = 8 ans = max(ans, 8) = 8
-
-
Result:
- The maximum total score possible is
8
, which is the value ofans
after processing all cells.
- The maximum total score possible is
Solution Implementation
1from typing import List
2from math import inf
3
4class Solution:
5 def maxScore(self, grid: List[List[int]]) -> int:
6 # Initialize a DP table with the same dimensions as the grid
7 f = [[0] * len(grid[0]) for _ in range(len(grid))]
8
9 # Initialize the variable to track the maximum score
10 max_score = -inf
11
12 # Iterate over each row in the grid
13 for i, row in enumerate(grid):
14 # Iterate over each element in the current row
15 for j, value in enumerate(row):
16 min_val = inf # Start with an infinitely large minimum value
17
18 # If not in the first row, update minimum value based on the cell above
19 if i > 0:
20 min_val = min(min_val, f[i - 1][j])
21
22 # If not in the first column, update the minimum value based on the previous cell in the row
23 if j > 0:
24 min_val = min(min_val, f[i][j - 1])
25
26 # Calculate the maximum score possible by subtracting the minimum path value found
27 max_score = max(max_score, value - min_val)
28
29 # Update the DP table with the minimum value on the path to (i, j)
30 f[i][j] = min(value, min_val)
31
32 return max_score
33
1import java.util.List;
2
3class Solution {
4 public int maxScore(List<List<Integer>> grid) {
5 // Define dimensions of the grid
6 int rows = grid.size(), columns = grid.get(0).size();
7
8 // Define a large positive number representing infinity
9 final int infinity = 1 << 30;
10
11 // Initialize the answer with negative infinity
12 int maxScore = -infinity;
13
14 // Create a 2D array for dynamic programming
15 int[][] minSoFar = new int[rows][columns];
16
17 // Traverse the grid row by row, column by column
18 for (int i = 0; i < rows; ++i) {
19 for (int j = 0; j < columns; ++j) {
20 // Initialize the minimum value with infinity
21 int currentMin = infinity;
22
23 // Update currentMin to the minimum value reached till the cell (i, j)
24 if (i > 0) {
25 currentMin = Math.min(currentMin, minSoFar[i - 1][j]);
26 }
27 if (j > 0) {
28 currentMin = Math.min(currentMin, minSoFar[i][j - 1]);
29 }
30
31 // Update maxScore considering the current cell's contribution
32 maxScore = Math.max(maxScore, grid.get(i).get(j) - currentMin);
33
34 // Track the minimum value reachable to the cell (i, j)
35 minSoFar[i][j] = Math.min(grid.get(i).get(j), currentMin);
36 }
37 }
38
39 // Return the maximum score
40 return maxScore;
41 }
42}
43
1class Solution {
2public:
3 int maxScore(vector<vector<int>>& grid) {
4 int rows = grid.size(); // Number of rows in the grid
5 int cols = grid[0].size(); // Number of columns in the grid
6 const int inf = 1 << 30; // A large constant to simulate infinity
7 int maxScoreVal = -inf; // Initialize the maximum score result
8 int minPathValue[rows][cols]; // Array to keep track of minimum path values
9
10 for (int i = 0; i < rows; ++i) {
11 for (int j = 0; j < cols; ++j) {
12 int minVal = inf; // Minimum value encountered up to the current cell
13 if (i > 0) {
14 // Check and update the minimum value from the top cell
15 minVal = min(minVal, minPathValue[i - 1][j]);
16 }
17 if (j > 0) {
18 // Check and update the minimum value from the left cell
19 minVal = min(minVal, minPathValue[i][j - 1]);
20 }
21 // Calculate the potential max score for this position
22 maxScoreVal = max(maxScoreVal, grid[i][j] - minVal);
23 // Set the minimum path value for the current cell
24 minPathValue[i][j] = min(grid[i][j], minVal);
25 }
26 }
27
28 return maxScoreVal; // Return the maximum score computed
29 }
30};
31
1function maxScore(grid: number[][]): number {
2 // Retrieve dimensions of the grid
3 const [m, n] = [grid.length, grid[0].length];
4
5 // Initialize a 2D array f with the same dimensions as the grid, filled with 0
6 const f: number[][] = Array.from({ length: m }, () => Array.from({ length: n }, () => 0));
7
8 // Initialize the answer to negative infinity
9 let ans = -Infinity;
10
11 // Iterate over each cell in the grid
12 for (let i = 0; i < m; ++i) {
13 for (let j = 0; j < n; ++j) {
14 // Initialize minimum value for f as Infinity
15 let minValue = Infinity;
16
17 // If not on the first row, consider the value from the cell above
18 if (i) {
19 minValue = Math.min(minValue, f[i - 1][j]);
20 }
21
22 // If not on the first column, consider the value from the cell to the left
23 if (j) {
24 minValue = Math.min(minValue, f[i][j - 1]);
25 }
26
27 // Update the answer with the maximum score found so far
28 ans = Math.max(ans, grid[i][j] - minValue);
29
30 // Set the current cell in f to the minimum of the current grid value and the minimum value calculated
31 f[i][j] = Math.min(minValue, grid[i][j]);
32 }
33 }
34
35 // Return the maximum score
36 return ans;
37}
38
Time and Space Complexity
The time complexity of the code is O(m * n)
because there are m
rows and n
columns in the grid, and the code iterates over each cell of the matrix exactly once. Within each iteration, only constant-time operations are performed, such as min and max calculations.
The space complexity of the code is also O(m * n)
due to the auxiliary matrix f
created to store intermediate results. This matrix is the same size as the input grid, requiring space proportional to the number of elements in the grid.
Learn more about how to find time and space complexity quickly.
A heap is a ...?
Recommended Readings
What is Dynamic Programming Prerequisite DFS problems dfs_intro Backtracking problems backtracking Memoization problems memoization_intro Pruning problems backtracking_pruning Dynamic programming is an algorithmic optimization technique that breaks down a complicated problem into smaller overlapping sub problems in a recursive manner and uses solutions to the sub problems to construct a solution
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https algomonster s3 us east 2 amazonaws com recursion jpg You first
Want a Structured Path to Master System Design Too? Don’t Miss This!