1706. Where Will the Ball Fall

Where Will the Ball Fall

Where Will the Ball Fall


You have a 2-D grid size m x n representing a box, and you have n balls. The box is open on the top and bottom sides.

Each cell in the box has a diagonal board spanning two corners of the cell that can redirect a ball to the right or to the left.

  • A board that redirects the ball to the right spans the top-left corner to the bottom-right corner and is represented in the grid as 1.
  • A board that redirects the ball to the left spans the top-right corner to the bottom-left corner and is represented in the grid as -1.

We drop one ball at the top of each column of the box. Each ball can get stuck in the box or fall out of the bottom. A ball gets stuck if it hits a "V" shaped pattern between two boards or if a board redirects the ball into either wall of the box.

Return an array answer of size n where answer[i] is the column that the ball falls out of at the bottom after dropping the ball from the ith column at the top, or -1 if the ball gets stuck in the box.

 

Example 1:

Where Will the Ball Fall - Example


Input: grid = [[1,1,1,-1,-1],[1,1,1,-1,-1],[-1,-1,-1,1,1],[1,1,1,1,-1],[-1,-1,-1,-1,-1]]
Output: [1,-1,-1,-1,-1]

Explanation: This example is shown in the photo.
Ball b0 is dropped at column 0 and falls out of the box at column 1.
Ball b1 is dropped at column 1 and will get stuck in the box between column 2 and 3 and row 1.
Ball b2 is dropped at column 2 and will get stuck on the box between column 2 and 3 and row 0.
Ball b3 is dropped at column 3 and will get stuck on the box between column 2 and 3 and row 0.
Ball b4 is dropped at column 4 and will get stuck on the box between column 2 and 3 and row 1.


Example 2:

Input: grid = [[-1]]
Output: [-1]

Explanation: The ball gets stuck against the left wall.


Example 3:

Input: grid = [[1,1,1,1,1,1],[-1,-1,-1,-1,-1,-1],[1,1,1,1,1,1],[-1,-1,-1,-1,-1,-1]]
Output: [0,1,2,3,4,-1]

 

Constraints:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 100
  • grid[i][j] is 1 or -1.

Approach) Brute Force

const findBall = function(grid) {
    const m = grid.length;
    const n = grid[0].length;
    const res = [];
    
    for(let i = 0; i < n; i++) {
        let r = 0;
        let c = i;
        while(r < m && r >= 0 && c < n) {
            if(grid[r][c] === 1 && grid[r][c] === grid[r][c+1]) {
                r++;
                c++;
            }
            else if(grid[r][c] === -1 && grid[r][c] === grid[r][c-1]) {
                r++;
                c--;
            }
            else break;
        }
        if(r === m) res.push(c);
        else res.push(-1);
    }
    
    return res;
};

Approach) DFS (Depth-First-Search)

function findBall(grid: number[][]): number[] {
  const answer = [];
  for(let i = 0 ; i < grid[0].length ; i++)
    answer[i] = dfs(0, i, grid);
  return answer;
};

function dfs(row: number, column: number, grid: number[][]) {
  if(row === grid.length)
    return column;
  if(isBlockedEdge(row, column, grid) || isVShaped(row, column, grid))
    return -1;
  return dfs(row + 1, column + grid[row][column], grid);
}

function isBlockedEdge(row, column, grid){
  return grid[row][column] === 1 && column === grid[0].length - 1 || grid[row][column] === -1 && column === 0;
}

function isVShaped(row, column, grid){
  return grid[row][column] === 1 && grid[row][column + 1] === -1 || grid[row][column] === -1 && grid[row][column - 1] === 1;
}

Approach) Another DFS (Depth-First-Search - Recursion)

var findBall = function(grid) { 
    function dfs(row, col) {
        if (row === grid.length) return col;
        let dir = grid[row][col];
        if (dir === 1 && grid[row][col + 1] === 1) return dfs(row + 1, col + 1);
        if (dir === -1 && grid[row][col - 1] === -1) return dfs(row + 1, col - 1);
        return -1;
    }
    const output = [];
    for (let i = 0; i < grid[0].length; i++) output.push(dfs(0, i));
    return output;
};

Approach) Dynamic Programming

/**
 * @param {number[][]} grid
 * @return {number[]}
 */
function findBall(grid) {
  const rowCount = grid.length
  const colCount = grid[0].length
  const dp = build2DArray(rowCount, colCount)

  const result = []

  for (let i = 0; i < colCount; i++) {
    // ball start from the top most position
    let currentPosition = { row: 0, col: i }
    let canThisBallPass = true

    // in order to update the dp
    const path = []

    while (currentPosition.row < rowCount) {
      path.push(currentPosition)

      if (dp[currentPosition.row][currentPosition.col] !== null) {
        canThisBallPass = dp[currentPosition.row][currentPosition.col]
        break
      }

      const [isStuck, nextPosition] = getNextPosition(currentPosition, grid)

      if (isStuck) {
        canThisBallPass = false
        break
      } else {
        currentPosition = nextPosition
      }
    }

    // update dp
    path.forEach((position) => {
      dp[position.row][position.col] = canThisBallPass
    })

    result.push(canThisBallPass ? currentPosition.col : -1)
  }

  return result
}

const build2DArray = (row, col) => {
  return Array(row)
    .fill()
    .map(() => Array(col).fill(null))
}

/**
 * @return {[isStuck, nextPosition]}
 */
const getNextPosition = (currentPosition, grid) => {
  if (grid[currentPosition.row][currentPosition.col] === 1) {
    if (
      currentPosition.col + 1 === grid[0].length || // it's a "\|"
      grid[currentPosition.row][currentPosition.col + 1] === -1 // it's a "\/"
    ) {
      return [true, null]
    }

    return [
      false,
      { row: currentPosition.row + 1, col: currentPosition.col + 1 },
    ]
  }

  if (
    currentPosition.col === 0 || // it's a "|/"
    grid[currentPosition.row][currentPosition.col - 1] === 1 // it's a "\/"
  ) {
    return [true, null]
  }

  return [false, { row: currentPosition.row + 1, col: currentPosition.col - 1 }]
}

Conclusion

That’s all folks! In this post, we solved LeetCode problem #1706. Where Will the Ball Fall

I hope you have enjoyed this post. Feel free to share your thoughts on this.

You can find the complete source code on my GitHub repository. If you like what you learn. feel free to fork 🔪 and star ⭐ it.


In this blog, I have tried to collect & present the most important points to consider when improving Data structure and logic, feel free to add, edit, comment, or ask. For more information please reach me here
Happy coding!




Comments

Popular Post