- categories: Code, Interview Question, leetcode, Medium
- source: https://leetcode.com/problems/snakes-and-ladders
- topics: 2D Array, Graph, BFS
Description
You are given an n x n
integer matrix board
where the cells are labeled from 1
to n2
in a Boustrophedon style starting from the bottom left of the board (i.e. board[n - 1][0]
) and alternating direction each row.
You start on square 1
of the board. In each move, starting from square curr
, do the following:
- Choose a destination square
next
with a label in the range[curr + 1, min(curr + 6, n2)]
.- This choice simulates the result of a standard 6-sided die roll: i.e., there are always at most 6 destinations, regardless of the size of the board.
- If
next
has a snake or ladder, you must move to the destination of that snake or ladder. Otherwise, you move tonext
. - The game ends when you reach the square
n2
.
A board square on row r
and column c
has a snake or ladder if board[r][c] != -1
. The destination of that snake or ladder is board[r][c]
. Squares 1
and n2
are not the starting points of any snake or ladder.
Note that you only take a snake or ladder at most once per dice roll. If the destination to a snake or ladder is the start of another snake or ladder, you do not follow the subsequent snake or ladder.
- For example, suppose the board is
[[-1,4],[-1,3]]
, and on the first move, your destination square is2
. You follow the ladder to square3
, but do not follow the subsequent ladder to4
.
Return the least number of dice rolls required to reach the square n2
. If it is not possible to reach the square, return -1
.
Idea
- Flatten the array + BFS
Code
class Solution:
def snakesAndLadders(self, board: List[List[int]]) -> int:
# Flatten to 1D array
flatten = []
for k in range(len(board)):
i = len(board) - k - 1
generator = (range(len(board[i])) if k % 2 == 0
else range(len(board[i])-1, -1, -1))
for j in generator:
flatten.append(board[i][j])
# BFS
min_paths = [inf] * len(flatten)
q = deque([0])
min_paths[0] = 0
while q:
curr = q.popleft()
for next_pos in range(curr+1, min(curr+7, len(flatten)), 1):
target = flatten[next_pos] - 1 if flatten[next_pos] > 0 else next_pos
if min_paths[target] > min_paths[curr] + 1:
min_paths[target] = min_paths[curr] + 1
q.append(target)
return min_paths[-1] if min_paths[-1] < inf else -1