[LeetCode] 909. Snakes and Ladders

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 to next.
  • 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 do not have a snake or ladder.

Note that you only take a snake or ladder at most once per move. 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 is 2. You follow the ladder to square 3, but do not follow the subsequent ladder to 4.

Return the least number of moves required to reach the square n2. If it is not possible to reach the square, return -1.

Example 1:

Input: board = [[-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1],[-1,35,-1,-1,13,-1],[-1,-1,-1,-1,-1,-1],[-1,15,-1,-1,-1,-1]]
Output: 4
Explanation: 
In the beginning, you start at square 1 (at row 5, column 0).
You decide to move to square 2 and must take the ladder to square 15.
You then decide to move to square 17 and must take the snake to square 13.
You then decide to move to square 14 and must take the ladder to square 35.
You then decide to move to square 36, ending the game.
This is the lowest possible number of moves to reach the last square, so return 4.

Example 2:

Input: board = [[-1,-1],[-1,3]]
Output: 1

Constraints:

  • n == board.length == board[i].length
  • 2 <= n <= 20
  • board[i][j] is either -1 or in the range [1, n2].
  • The squares labeled 1 and n2 do not have any ladders or snakes.

蛇梯棋。

给你一个大小为 n x n 的整数矩阵 board ,方格按从 1 到 n2 编号,编号遵循 转行交替方式 ,从左下角开始 (即,从 board[n - 1][0] 开始)每一行交替方向。

玩家从棋盘上的方格 1 (总是在最后一行、第一列)开始出发。

每一回合,玩家需要从当前方格 curr 开始出发,按下述要求前进:

选定目标方格 next ,目标方格的编号符合范围 [curr + 1, min(curr + 6, n2)] 。
该选择模拟了掷 六面体骰子 的情景,无论棋盘大小如何,玩家最多只能有 6 个目的地。
传送玩家:如果目标方格 next 处存在蛇或梯子,那么玩家会传送到蛇或梯子的目的地。否则,玩家传送到目标方格 next 。 
当玩家到达编号 n2 的方格时,游戏结束。
r 行 c 列的棋盘,按前述方法编号,棋盘格中可能存在 “蛇” 或 “梯子”;如果 board[r][c] != -1,那个蛇或梯子的目的地将会是 board[r][c]。编号为 1 和 n2 的方格上没有蛇或梯子。

注意,玩家在每回合的前进过程中最多只能爬过蛇或梯子一次:就算目的地是另一条蛇或梯子的起点,玩家也 不能 继续移动。

举个例子,假设棋盘是 [[-1,4],[-1,3]] ,第一次移动,玩家的目标方格是 2 。那么这个玩家将会顺着梯子到达方格 3 ,但 不能 顺着方格 3 上的梯子前往方格 4 。
返回达到编号为 n2 的方格所需的最少移动次数,如果不可能,则返回 -1。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/snakes-and-ladders
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路是 BFS。这道题本身不是特别难,但是理解题意花了点功夫。题意是给一个二维数组,你是从左下角那个位置开始走,看是否能走到最后一个格子。这个题的一个坑在于你不知道最后一个格子在最上面一行(i == 0)的最左边还是最右边,所以这里我们需要把这个二维数组扁平化。假设这个矩阵的尺寸是 m * n,扁平化之后,我们在意的就只是我们是否能走到 index = m * n 的位置上(注意 index 从 1 开始)。

所以我们需要把这个二维数组里的所有 index 做一个扁平化操作,把他们放到一个一维的数组里。扁平化操作结束之后,因为我们是通过掷骰子的方式决定往前能走几步,所以我们需要探测走 [1, 6] 的可能性。如果遇到的是梯子或者蛇(board[i][j] != -1),那么我们就根据 board[i][j] 的值走到下一个位置上去。最后注意我们还需要一个 hashmap 记录我们遍历到每个 index 都花了几步;如果某个 index 被访问过了,BFS 的时候也记得跳过,不要重复处理。

时间O(n)

空间O(n)

Java实现

 1 class Solution {
 2     public int snakesAndLadders(int[][] board) {
 3         // corner case
 4         if (board == null || board.length == 0) {
 5             return 0;
 6         }
 7 
 8         // normal case
 9         int n = board.length;
10         boolean isRight = true;
11 
12         int[] nums = new int[n * n + 1];
13         int index = 1;
14         for (int i = n - 1; i >= 0; i--) {
15             if (isRight) {
16                 for (int j = 0; j < n; j++) {
17                     nums[index++] = board[i][j];
18                 }
19             } else {
20                 for (int j = n - 1; j >= 0; j--) {
21                     nums[index++] = board[i][j];
22                 }
23             }
24             isRight = !isRight;
25         }
26 
27         // BFS
28         Queue<Integer> queue = new LinkedList<>();
29         HashMap<Integer, Integer> map = new HashMap<>();
30         queue.offer(1);
31         map.put(1, 0);
32         while (!queue.isEmpty()) {
33             int curIndex = queue.poll();
34             int step = map.get(curIndex);
35             if (curIndex == n * n) {
36                 return step;
37             }
38             for (int i = 1; i <= 6; i++) {
39                 int newIndex = curIndex + i;
40                 if (newIndex <= 0 || newIndex > n * n) {
41                     continue;
42                 }
43                 // if snake or ladder
44                 if (nums[newIndex] != -1) {
45                     newIndex = nums[newIndex];
46                 }
47                 // 走过的index就无须再看了,步数只会更多
48                 if (map.containsKey(newIndex)) {
49                     continue;
50                 }
51                 queue.offer(newIndex);
52                 map.put(newIndex, step + 1);
53             }
54         }
55         return -1;
56     }
57 }

 

LeetCode 题目总结

posted @ 2023-01-27 11:45  CNoodle  阅读(39)  评论(0编辑  收藏  举报