Grid Game
MedPrompt
You are given a 0-indexed 2D array grid of size 2 x n, where grid[r][c] represents the number of points at position (r, c) on the matrix. Two robots are playing a game on this matrix.
Both robots initially start at (0, 0) and want to reach (1, n-1). Each robot may only move to the right ((r, c) to (r, c + 1)) or down ((r, c) to (r + 1, c)).
At the start of the game, the first robot moves from (0, 0) to (1, n-1), collecting all the points from the cells on its path. For all cells (r, c) traversed on the path, grid[r][c] is set to 0. Then, the second robot moves from (0, 0) to (1, n-1), collecting the points on its path. Note that their paths may intersect with one another.
The first robot wants to minimize the number of points collected by the second robot. In contrast, the second robot wants to maximize the number of points it collects. If both robots play optimally, return the number of points collected by the second robot.
Example 1:
Input: grid = [[2,5,4],[1,5,1]]
Output: 4
Explanation: The optimal path taken by the first robot is shown in red, and the optimal path taken by the second robot is shown in blue.
The cells visited by the first robot are set to 0.
The second robot will collect 0 + 0 + 4 + 0 = 4 points.Example 2:
Input: grid = [[3,3,1],[8,5,2]]
Output: 4
Explanation: The optimal path taken by the first robot is shown in red, and the optimal path taken by the second robot is shown in blue.
The cells visited by the first robot are set to 0.
The second robot will collect 0 + 3 + 1 + 0 = 4 points.Example 3:
Input: grid = [[1,3,1,15],[1,3,3,1]]
Output: 7
Explanation: The optimal path taken by the first robot is shown in red, and the optimal path taken by the second robot is shown in blue.
The cells visited by the first robot are set to 0.
The second robot will collect 0 + 1 + 3 + 3 + 0 = 7 points.
Constraints:
grid.length == 2n == grid[r].length1 <= n <= 5 * 1041 <= grid[r][c] <= 105
Approaches
3 approaches with complexity analysis and trade-offs.
This approach directly simulates the game based on our understanding of the optimal strategies. The first robot can choose n different paths, each defined by the column i where it moves from the top row to the bottom row. For each of these n choices, we calculate the maximum score the second robot can achieve and then find the minimum among these scores.
Algorithm
- Initialize
minResultto a very large number (e.g.,Long.MAX_VALUE). - Iterate
ifrom0ton-1, wherenis the number of columns. Thisirepresents the column where the first robot switches from the top row to the bottom row. - Inside the loop, for each
i:- Initialize
topSum = 0andbottomSum = 0. - Calculate
topSumby iterating fromj = i + 1ton-1and summing upgrid[0][j]. - Calculate
bottomSumby iterating fromj = 0toi-1and summing upgrid[1][j]. - The second robot will choose the path that yields the maximum score, which is
max(topSum, bottomSum). - The first robot wants to minimize this score, so we update our overall result:
minResult = min(minResult, max(topSum, bottomSum)).
- Initialize
- After the loop finishes,
minResultwill hold the score of the second robot when both play optimally. ReturnminResult.
Walkthrough
The core idea is to iterate through every possible path for the first robot. A path is uniquely determined by the column i (from 0 to n-1) where the robot switches from row 0 to row 1.
For a fixed i, the first robot clears the path (0,0) -> ... -> (0,i) -> (1,i) -> ... -> (1,n-1). After this, the grid is effectively split into two sections of available points for the second robot:
- The points in the top row to the right of column
i:grid[0][i+1]togrid[0][n-1]. - The points in the bottom row to the left of column
i:grid[1][0]togrid[1][i-1].
The second robot, to maximize its score, will choose a path that collects all points from one of these two sections. Its score will be the maximum of the sum of points in these two sections.
We can iterate through each possible i from 0 to n-1. In each iteration, we calculate the sum of the top-right part and the bottom-left part. We take the maximum of these two sums, which is the score the second robot gets for this i. We keep track of the minimum of these maximum scores over all i. This minimum value is the answer, as the first robot will choose the i that leads to this outcome.
class Solution { public long gridGame(int[][] grid) { int n = grid[0].length; long minMaxScore = Long.MAX_VALUE; for (int i = 0; i < n; i++) { // Simulate Robot 1's path switching at column i // Calculate score for Robot 2's top path option long topPathScore = 0; for (int j = i + 1; j < n; j++) { topPathScore += grid[0][j]; } // Calculate score for Robot 2's bottom path option long bottomPathScore = 0; for (int j = 0; j < i; j++) { bottomPathScore += grid[1][j]; } // Robot 2 chooses the path with the maximum score long secondRobotScore = Math.max(topPathScore, bottomPathScore); // Robot 1 chooses i to minimize Robot 2's score minMaxScore = Math.min(minMaxScore, secondRobotScore); } return minMaxScore; }}Complexity
Time
O(n^2), where n is the number of columns. The outer loop runs `n` times. Inside the loop, we have two more loops to calculate the sums, each taking up to O(n) time.
Space
O(1), as we only use a few variables to store the sums and the result, regardless of the input size.
Trade-offs
Pros
Simple to understand and implement directly from the problem's logic.
It correctly models the game's minimax nature.
Cons
This approach is inefficient due to the nested loops, leading to a quadratic time complexity.
For the given constraints (n up to 5 * 10^4), this solution will be too slow and result in a 'Time Limit Exceeded' error on most platforms.
The brute-force approach is slow because we repeatedly calculate sums over subarrays. This can be optimized by pre-calculating prefix sums for both rows. With prefix sums, we can find the sum of any subarray in O(1) time, which reduces the overall time complexity significantly.
Algorithm
- Get
n, the number of columns. - Create two prefix sum arrays,
prefixSumTopandprefixSumBottom, each of sizen+1. - Populate
prefixSumTop:prefixSumTop[i] = prefixSumTop[i-1] + grid[0][i-1]forifrom 1 ton. - Populate
prefixSumBottom:prefixSumBottom[i] = prefixSumBottom[i-1] + grid[1][i-1]forifrom 1 ton. - Initialize
minResulttoLong.MAX_VALUE. - Iterate
ifrom0ton-1.- Calculate the sum of the top row from
i+1ton-1astopSum = prefixSumTop[n] - prefixSumTop[i+1]. - The sum of the bottom row from
0toi-1is directlybottomSum = prefixSumBottom[i]. - The second robot's score for this
iissecondRobotScore = max(topSum, bottomSum). - Update
minResult = min(minResult, secondRobotScore).
- Calculate the sum of the top row from
- Return
minResult.
Walkthrough
We can create two prefix sum arrays, one for each row of the grid. prefixSumTop[i] will store the sum of elements from grid[0][0] to grid[0][i-1], and prefixSumBottom[i] will store the cumulative sum for grid[1]. Building these arrays takes O(n) time.
After building these arrays, we can revisit the main loop from the brute-force approach. For each possible switch column i for the first robot:
- The sum of the top row from
i+1ton-1(the first choice for robot 2) can be calculated in O(1) astotalSumTop - prefixSumTop[i+1].totalSumTopis simplyprefixSumTop[n]. - The sum of the bottom row from
0toi-1(the second choice for robot 2) is directly available asprefixSumBottom[i].
The rest of the logic remains the same: find the maximum of these two sums for each i, and then find the minimum of these maximums over all i. This brings the time complexity down to a linear scan.
class Solution { public long gridGame(int[][] grid) { int n = grid[0].length; long[] prefixSumTop = new long[n + 1]; long[] prefixSumBottom = new long[n + 1]; for (int i = 0; i < n; i++) { prefixSumTop[i + 1] = prefixSumTop[i] + grid[0][i]; prefixSumBottom[i + 1] = prefixSumBottom[i] + grid[1][i]; } long minMaxScore = Long.MAX_VALUE; for (int i = 0; i < n; i++) { // Sum of points in top row to the right of i long topPathScore = prefixSumTop[n] - prefixSumTop[i + 1]; // Sum of points in bottom row to the left of i long bottomPathScore = prefixSumBottom[i]; long secondRobotScore = Math.max(topPathScore, bottomPathScore); minMaxScore = Math.min(minMaxScore, secondRobotScore); } return minMaxScore; }}Complexity
Time
O(n). We have one pass to build the prefix sum arrays (O(n)) and another pass to iterate through `i` (O(n)). This gives a total of O(n).
Space
O(n), as we use two extra arrays of size `n+1` to store the prefix sums.
Trade-offs
Pros
Significantly faster than the brute-force approach, with a linear time complexity.
Efficient enough to pass the given constraints.
Cons
Uses extra space proportional to the input size, which might be a concern for very large inputs under strict memory constraints.
We can further optimize the prefix sum approach to use constant extra space. Instead of pre-calculating and storing all prefix sums in arrays, we can maintain the two required sums (topSum and bottomSum) and update them dynamically as we iterate through the columns in a single pass.
Algorithm
- Get
n, the number of columns. - Calculate
topSumas the total sum ofgrid[0]. - Initialize
bottomSum = 0. - Initialize
minResult = Long.MAX_VALUE. - Iterate
ifrom0ton-1.- Update
topSumby subtractinggrid[0][i]. This represents the remaining points on the top row if robot 1 switches ati. - The second robot's score for this
iismax(topSum, bottomSum). - Update
minResult = min(minResult, max(topSum, bottomSum)). - Update
bottomSumby addinggrid[1][i]. This preparesbottomSumfor the next iteration (i+1).
- Update
- Return
minResult.
Walkthrough
This approach avoids creating separate prefix sum arrays. We can achieve the same result in a single pass.
First, calculate the total sum of the top row. Let's call this topSum. Initialize bottomSum to 0.
Now, iterate i from 0 to n-1. In each step, i represents the current switch-down column for the first robot.
- Subtract
grid[0][i]fromtopSum. NowtopSumrepresents the sum of points to the right of columniin the top row. - At this point,
topSumis the score from the top path option for Robot 2, andbottomSumis the score from the bottom path option (which represents the sum of points ingrid[1]from0toi-1). - Calculate
max(topSum, bottomSum)and update our overall minimum result. - Add
grid[1][i]tobottomSum. This preparesbottomSumfor the next iteration, where it will represent the sum of points to the left of columni+1.
This way, we correctly calculate the two competing scores for Robot 2 at each possible switch point i for Robot 1, all within a single loop and with constant extra space.
class Solution { public long gridGame(int[][] grid) { int n = grid[0].length; long topSum = 0; for (int point : grid[0]) { topSum += point; } long bottomSum = 0; long minMaxScore = Long.MAX_VALUE; for (int i = 0; i < n; i++) { // Robot 1 moves along top row, taking grid[0][i] at this step. topSum -= grid[0][i]; // At this point: // topSum is the sum of points in grid[0] from i+1 to n-1. // bottomSum is the sum of points in grid[1] from 0 to i-1. // These are the two choices for Robot 2. long secondRobotScore = Math.max(topSum, bottomSum); minMaxScore = Math.min(minMaxScore, secondRobotScore); // Robot 1 also clears grid[1][i] on its path. For the next iteration (i+1), // this point becomes available for Robot 2's bottom path choice. bottomSum += grid[1][i]; } return minMaxScore; }}Complexity
Time
O(n). We have an initial pass to sum the top row (O(n)) and a second pass to iterate through the columns (O(n)). This is O(n) in total.
Space
O(1), as we only use a few variables to store the running sums and the result, independent of the input size `n`.
Trade-offs
Pros
Most efficient solution in both time (O(n)) and space (O(1)).
It's a clean, single-pass solution after an initial sum calculation.
Cons
The logic for updating the running sums might be slightly less intuitive at first glance compared to the explicit prefix sum array approach.
Solutions
Solution
class Solution {public long gridGame(int[][] grid) { long ans = Long.MAX_VALUE; long s1 = 0, s2 = 0; for (int v : grid[0]) { s1 += v; } int n = grid[0].length; for (int j = 0; j < n; ++j) { s1 -= grid[0][j]; ans = Math.min(ans, Math.max(s1, s2)); s2 += grid[1][j]; } return ans; }}using ll = long long ; class Solution { public: long long gridGame ( vector < vector < int >>& grid ) { ll ans = LONG_MAX ; int n = grid [ 0 ]. size (); ll s1 = 0 , s2 = 0 ; for ( int & v : grid [ 0 ]) s1 += v ; for ( int j = 0 ; j < n ; ++ j ) { s1 -= grid [ 0 ][ j ]; ans = min ( ans , max ( s1 , s2 )); s2 += grid [ 1 ][ j ]; } return ans ; } };class Solution: def gridGame(self, grid: List[List[int]]) -> int: ans = inf s1, s2 = sum(grid[0]), 0 for j, v in enumerate(grid[0]): s1 -= v ans = min(ans, max(s1, s2)) s2 += grid[1][j] return ansVideo walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.