Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

1706. Where Will the Ball Fall - Leetcode Solution

Code Implementation

class Solution:
    def findBall(self, grid):
        m, n = len(grid), len(grid[0])
        res = []
        for col in range(n):
            curr_col = col
            for row in range(m):
                dir = grid[row][curr_col]
                next_col = curr_col + dir
                # Check if next_col is out of bounds or forms a V shape
                if next_col < 0 or next_col >= n or grid[row][next_col] != dir:
                    curr_col = -1
                    break
                curr_col = next_col
            res.append(curr_col)
        return res
      
class Solution {
public:
    vector<int> findBall(vector<vector<int>>& grid) {
        int m = grid.size(), n = grid[0].size();
        vector<int> res(n, 0);
        for (int col = 0; col < n; ++col) {
            int curr_col = col;
            for (int row = 0; row < m; ++row) {
                int dir = grid[row][curr_col];
                int next_col = curr_col + dir;
                if (next_col < 0 || next_col >= n || grid[row][next_col] != dir) {
                    curr_col = -1;
                    break;
                }
                curr_col = next_col;
            }
            res[col] = curr_col;
        }
        return res;
    }
};
      
class Solution {
    public int[] findBall(int[][] grid) {
        int m = grid.length, n = grid[0].length;
        int[] res = new int[n];
        for (int col = 0; col < n; col++) {
            int curr_col = col;
            for (int row = 0; row < m; row++) {
                int dir = grid[row][curr_col];
                int next_col = curr_col + dir;
                if (next_col < 0 || next_col >= n || grid[row][next_col] != dir) {
                    curr_col = -1;
                    break;
                }
                curr_col = next_col;
            }
            res[col] = curr_col;
        }
        return res;
    }
}
      
var findBall = function(grid) {
    let m = grid.length, n = grid[0].length;
    let res = [];
    for (let col = 0; col < n; col++) {
        let curr_col = col;
        for (let row = 0; row < m; row++) {
            let dir = grid[row][curr_col];
            let next_col = curr_col + dir;
            if (next_col < 0 || next_col >= n || grid[row][next_col] != dir) {
                curr_col = -1;
                break;
            }
            curr_col = next_col;
        }
        res.push(curr_col);
    }
    return res;
};
      

Problem Description

You are given a 2D grid representing a box with m rows and n columns. Each cell in the grid contains either 1 or -1:

  • 1 means the cell's board slopes to the right
  • -1 means the cell's board slopes to the left
At the top of each column, a ball is dropped. The ball will roll down, moving right if it hits a 1 or left if it hits a -1. However, if the ball hits the wall or gets stuck in a "V" shape (two adjacent boards sloping towards each other), it will get stuck and not fall out.

Your task is to return an array where the i-th element is the column index where the ball dropped in column i will fall out at the bottom, or -1 if it gets stuck.

Thought Process

To solve this problem, let's first imagine dropping a ball from each column and simulating its journey through the grid. At each step, the ball moves according to the slope in the current cell:

  • If the cell is 1, the ball tries to move right.
  • If the cell is -1, the ball tries to move left.
However, complications arise if:
  • The ball tries to move out of the grid (leftmost or rightmost column).
  • The ball encounters a "V" shape (i.e., two adjacent cells in the same row have opposite slopes), which traps the ball.
A brute-force approach would be to simulate the ball's path for each column, but we should look for ways to optimize the process, perhaps by minimizing redundant checks or using early exits when the ball gets stuck.

Solution Approach

The solution involves simulating the path of each ball as it moves down the grid. Here is a step-by-step breakdown:

  1. For each column at the top (from 0 to n-1), drop a ball and track its current column position.
  2. For each row in the grid:
    • Check the direction of the slope in the current cell (1 or -1).
    • Calculate the next column the ball would move to (curr_col + dir).
    • Check for stuck conditions:
      • If the next column is out of bounds (less than 0 or greater than or equal to n), the ball is stuck.
      • If the direction in the next cell is different from the current cell (i.e., forms a "V" shape), the ball is stuck.
    • If not stuck, update the current column to the next column and continue to the next row.
  3. If the ball makes it through all rows, record its final column; otherwise, record -1 for that ball.
The main design choice is to use a simple loop for each ball, as each ball's path is independent and the grid is small enough to allow direct simulation.

Example Walkthrough

Let's consider the following grid as an example:

    grid = [
      [1, 1, -1, -1],
      [-1, -1, 1, 1],
      [1, 1, 1, -1]
    ]
    
Let's trace the ball dropped at column 0:
  • Row 0, col 0: cell is 1 (go right to col 1)
  • Row 1, col 1: cell is -1 (go left to col 0)
  • But grid[1][0] is -1, which matches direction, so continue
  • Row 2, col 0: cell is 1 (go right to col 1)
  • grid[2][1] is 1, direction matches, so continue
  • Ball exits at column 1
Now, let's trace the ball dropped at column 2:
  • Row 0, col 2: cell is -1 (go left to col 1)
  • grid[0][1] is 1, which does not match direction, so it's a "V" shape and the ball gets stuck
  • Return -1 for this ball
Repeat this for all columns to get the final answer.

Time and Space Complexity

Brute-force Approach:

  • For each ball (n columns), simulate its path through all rows (m rows).
  • Time complexity: O(m * n), since each cell is visited at most once per ball.
  • Space complexity: O(n) for the result array.
Optimized Approach:
  • The direct simulation described above is already optimal for this problem, as each ball is independent and the grid is not modified.
  • No extra space is needed beyond the output array.
  • Thus, time: O(m * n), space: O(n).

Summary

The key to this problem is simulating the path of each ball as it moves through the grid, checking for stuck conditions at each step. By carefully handling edge cases (walls and "V" shapes), we can efficiently determine where each ball will end up. The solution is elegant because it leverages the independence of each ball's journey and uses straightforward iteration for clarity and efficiency.