|
| 1 | +/** |
| 2 | + * 909. Snakes and Ladders |
| 3 | + * https://leetcode.com/problems/snakes-and-ladders/ |
| 4 | + * Difficulty: Medium |
| 5 | + * |
| 6 | + * You are given an n x n integer matrix board where the cells are labeled from 1 to n2 in a |
| 7 | + * Boustrophedon style starting from the bottom left of the board (i.e. board[n - 1][0]) and |
| 8 | + * alternating direction each row. |
| 9 | + * |
| 10 | + * You start on square 1 of the board. In each move, starting from square curr, do the following: |
| 11 | + * - Choose a destination square next with a label in the range [curr + 1, min(curr + 6, n2)]. |
| 12 | + * - This choice simulates the result of a standard 6-sided die roll: i.e., there are always at |
| 13 | + * most 6 destinations, regardless of the size of the board. |
| 14 | + * - If next has a snake or ladder, you must move to the destination of that snake or ladder. |
| 15 | + * Otherwise, you move to next. |
| 16 | + * - The game ends when you reach the square n2. |
| 17 | + * |
| 18 | + * A board square on row r and column c has a snake or ladder if board[r][c] != -1. The destination |
| 19 | + * of that snake or ladder is board[r][c]. Squares 1 and n2 are not the starting points of any |
| 20 | + * snake or ladder. |
| 21 | + * |
| 22 | + * Note that you only take a snake or ladder at most once per dice roll. If the destination to a |
| 23 | + * snake or ladder is the start of another snake or ladder, you do not follow the subsequent snake |
| 24 | + * or ladder. |
| 25 | + * |
| 26 | + * - For example, suppose the board is [[-1,4],[-1,3]], and on the first move, your destination |
| 27 | + * square is 2. You follow the ladder to square 3, but do not follow the subsequent ladder to 4. |
| 28 | + * |
| 29 | + * Return the least number of dice rolls required to reach the square n2. If it is not possible to |
| 30 | + * reach the square, return -1. |
| 31 | + */ |
| 32 | + |
| 33 | +/** |
| 34 | + * @param {number[][]} board |
| 35 | + * @return {number} |
| 36 | + */ |
| 37 | +var snakesAndLadders = function(board) { |
| 38 | + const target = board.length * board.length; |
| 39 | + const queue = [1]; |
| 40 | + const seen = new Set([1]); |
| 41 | + let moves = 0; |
| 42 | + |
| 43 | + while (queue.length) { |
| 44 | + const size = queue.length; |
| 45 | + for (let i = 0; i < size; i++) { |
| 46 | + const current = queue.shift(); |
| 47 | + if (current === target) return moves; |
| 48 | + for (let dice = 1; dice <= 6 && current + dice <= target; dice++) { |
| 49 | + const next = current + dice; |
| 50 | + const [r, c] = getCoordinates(next); |
| 51 | + const destination = board[r][c] === -1 ? next : board[r][c]; |
| 52 | + if (!seen.has(destination)) { |
| 53 | + seen.add(destination); |
| 54 | + queue.push(destination); |
| 55 | + } |
| 56 | + } |
| 57 | + } |
| 58 | + moves++; |
| 59 | + } |
| 60 | + |
| 61 | + return -1; |
| 62 | + |
| 63 | + function getCoordinates(square) { |
| 64 | + const r = board.length - 1 - Math.floor((square - 1) / board.length); |
| 65 | + const c = (board.length - 1 - r) % 2 === 0 |
| 66 | + ? (square - 1) % board.length |
| 67 | + : board.length - 1 - (square - 1) % board.length; |
| 68 | + return [r, c]; |
| 69 | + } |
| 70 | +}; |
0 commit comments