You are given a rows x cols
matrix grid
representing a field of cherries where grid[i][j]
represents the number of cherries that you can collect from the (i, j)
cell.
You have two robots that can collect cherries for you:
(0, 0)
, and(0, cols - 1)
.Return the maximum number of cherries collection using both robots by following the rules below:
(i, j)
, robots can move to cell (i + 1, j - 1)
, (i + 1, j)
, or (i + 1, j + 1)
. The robots must stay within the bounds of the grid at all times.grid
.For example:
grid = [[3,1,1],[2,5,1],[1,5,5],[2,1,1]]
In this case, the maximum number of cherries that can be collected is 24.
grid = [[1,0,0,0,0,0,1],[2,0,0,0,0,3,0],[2,0,9,0,0,0,0],[0,3,0,5,4,0,0],[1,0,2,3,0,0,6]]
In this case, the maximum number of cherries that can be collected is 28.
What algorithm can you use to solve this problem?
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The cherry pickup problem asks us to find the most cherries two people can collect while walking through a grid. A brute force approach involves exploring every possible path each person could take and calculating the cherries they collect along the way.
Here's how the algorithm would work step-by-step:
def cherry_pickup_brute_force(grid):
rows = len(grid)
columns = len(grid[0])
def find_max_cherries(row, first_robot_column, second_robot_column):
# Base case: Reached the bottom row.
if row == rows:
return 0
max_cherries = 0
# Iterate through all possible moves for both robots.
for first_robot_move in [-1, 0, 1]:
for second_robot_move in [-1, 0, 1]:
new_first_robot_column = first_robot_column + first_robot_move
new_second_robot_column = second_robot_column + second_robot_move
# Check if the new columns are within bounds.
if 0 <= new_first_robot_column < columns and 0 <= new_second_robot_column < columns:
# Calculate the cherries collected in the current cell.
cherries = grid[row][new_first_robot_column]
if new_first_robot_column != new_second_robot_column:
cherries += grid[row][new_second_robot_column]
# Recursively calculate the maximum cherries from the next row.
cherries += find_max_cherries(row + 1, new_first_robot_column, new_second_robot_column)
max_cherries = max(max_cherries, cherries)
return max_cherries
# Start both robots at the top row, robot 1 at top-left and robot 2 at top-right
return find_max_cherries(0, 0, columns - 1)
The best way to solve this is to think about it dynamically, avoiding redundant calculations. Instead of trying all possible paths for both robots, we'll remember the best cherry count we can achieve from each location and reuse that information.
Here's how the algorithm would work step-by-step:
def cherry_pickup_ii(grid):
rows = len(grid)
columns = len(grid[0])
# Store the max cherries collected at each state.
maximum_cherries = [[[-1] * columns for _ in range(columns)] for _ in range(rows)]
def get_max_cherries(row, robot_one_column, robot_two_column):
if row == rows:
return 0
if robot_one_column < 0 or robot_one_column >= columns or \
robot_two_column < 0 or robot_two_column >= columns:
return float('-inf')
if maximum_cherries[row][robot_one_column][robot_two_column] != -1:
return maximum_cherries[row][robot_one_column][robot_two_column]
cherries = 0
if robot_one_column == robot_two_column:
cherries = grid[row][robot_one_column]
else:
cherries = grid[row][robot_one_column] + grid[row][robot_two_column]
# Explore all possible moves for both robots.
max_next_cherries = 0
for robot_one_move in [-1, 0, 1]:
for robot_two_move in [-1, 0, 1]:
next_robot_one_column = robot_one_column + robot_one_move
next_robot_two_column = robot_two_column + robot_two_move
# Recursively calculate the max cherries from the next row.
next_cherries = get_max_cherries(row + 1, next_robot_one_column, next_robot_two_column)
max_next_cherries = max(max_next_cherries, next_cherries)
maximum_cherries[row][robot_one_column][robot_two_column] = cherries + max_next_cherries
return maximum_cherries[row][robot_one_column][robot_two_column]
# Start the robots at the top corners.
return get_max_cherries(0, 0, columns - 1)
Case | How to Handle |
---|---|
Null or empty grid | Return 0 immediately as no cherries can be collected from an empty grid. |
Grid with only one row | The two robots start at (0,0) and (0, n-1), so sum the cherry values if distinct, else just the value at that column. |
Grid with only one column | The robots will always be at the same position, so the collected cherries equals the sum of all cells in the column. |
Maximum grid size (e.g., 70x70) and whether DP scales efficiently | Ensure that DP table dimensions are properly initialized and the algorithm does not exceed time limits. |
Grid containing negative numbers | Handle by ensuring the problem statement defines the values of the cherries are non-negative and that a constraint is added to prohibit negative numbers. |
Integer overflow when summing cherries | Use appropriate data types (e.g., long) to prevent integer overflow when summing cherry values. |
All cells have zero cherries | The result should be 0, and the algorithm needs to ensure it handles this corner case by providing a base case of 0 |
Robots meet at the same cell with cherries | The solution must only count the cherries from that cell once when robots occupy the same location. |