[LeetCode] 1730. Shortest Path to Get Food

You are starving and you want to eat food as quickly as possible. You want to find the shortest path to arrive at any food cell.

You are given an m x n character matrix, grid, of these different types of cells:

  • '*' is your location. There is exactly one '*' cell.
  • '#' is a food cell. There may be multiple food cells.
  • 'O' is free space, and you can travel through these cells.
  • 'X' is an obstacle, and you cannot travel through these cells.

You can travel to any adjacent cell north, east, south, or west of your current location if there is not an obstacle.

Return the length of the shortest path for you to reach any food cell. If there is no path for you to reach food, return -1.

Example 1:

Input: grid = [["X","X","X","X","X","X"],["X","*","O","O","O","X"],["X","O","O","#","O","X"],["X","X","X","X","X","X"]]
Output: 3
Explanation: It takes 3 steps to reach the food.

Example 2:

Input: grid = [["X","X","X","X","X"],["X","*","X","O","X"],["X","O","X","#","X"],["X","X","X","X","X"]]
Output: -1
Explanation: It is not possible to reach the food.

Example 3:

Input: grid = [["X","X","X","X","X","X","X","X"],["X","*","O","X","O","#","O","X"],["X","O","O","X","O","O","X","X"],["X","O","O","O","O","#","O","X"],["X","X","X","X","X","X","X","X"]]
Output: 6
Explanation: There can be multiple food cells. It only takes 6 steps to reach the bottom food.

Example 4:

Input: grid = [["O","*"],["#","O"]]
Output: 2

Example 5:

Input: grid = [["X","*"],["#","X"]]
Output: -1

Constraints:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 200
  • grid[row][col] is '*''X''O', or '#'.
  • The grid contains exactly one '*'.

获取食物的最短路径。

你现在很饿,想要尽快找东西吃。你需要找到最短的路径到达一个食物所在的格子。

给定一个 m x n 的字符矩阵 grid ,包含下列不同类型的格子:

'*' 是你的位置。矩阵中有且只有一个 '*' 格子。
'#' 是食物。矩阵中可能存在多个食物。
'O' 是空地,你可以穿过这些格子。
'X' 是障碍,你不可以穿过这些格子。

返回你到任意食物的最短路径的长度。 如果不存在你到任意食物的路径,返回 -1。

这是一道带有障碍物的 flood fill 类型的题。给了唯一的起点,用 X 表示,请你返回一个找到食物的最短距离。在矩阵里做搜索,如果要找最短距离,往往是 BFS

我们还是创建一个 queue,将起点放入 queue 中;同时我们需要一个与 input 矩阵同样大小的二维数组 visited 记录每个点是否被访问过。接着我们从起点开始遍历矩阵中每个有效的点。无效的点(障碍)是用 X 表示的,如果遇到了 X 则跳过不处理即可。我们需要关注的点是在矩阵范围内且没有被访问过的点。访问过之后,则将他放入 queue 接着往下找这些点自己的邻居节点。因为对于每个点来说你并不知道他最后找到食物是在哪个方向上,所以记录 step 的方式也跟一般 BFS 的题稍有区别。

时间O(mn)

空间O(mn)

Java实现

 1 class Solution {
 2     int[][] DIRS = { { 0, -1 }, { 0, 1 }, { 1, 0 }, { -1, 0 } };
 3 
 4     public int getFood(char[][] grid) {
 5         int m = grid.length;
 6         int n = grid[0].length;
 7         Queue<int[]> queue = new LinkedList<>();
 8         for (int i = 0; i < m; i++) {
 9             for (int j = 0; j < n; j++) {
10                 if (grid[i][j] == '*') {
11                     queue.offer(new int[] { i, j });
12                     break;
13                 }
14             }
15         }
16         boolean[][] visited = new boolean[m][n];
17 
18         int step = 0;
19         while (!queue.isEmpty()) {
20             int size = queue.size();
21             for (int i = 0; i < size; i++) {
22                 int[] cur = queue.poll();
23                 int x = cur[0];
24                 int y = cur[1];
25                 if (grid[x][y] == '#') {
26                     return step;
27                 }
28                 for (int[] dir : DIRS) {
29                     int r = x + dir[0];
30                     int c = y + dir[1];
31                     if (r >= 0 && r < m && c >= 0 && c < n && grid[r][c] != 'X' && !visited[r][c]) {
32                         visited[r][c] = true;
33                         queue.offer(new int[] { r, c });
34                     }
35                 }
36             }
37             step++;
38         }
39         return -1;
40     }
41 }

 

二刷我再提供一个不需要 visited 数组的代码。这里我直接把访问过的坐标标记为 X,就不会再次被处理了。

 1 class Solution {
 2     int m;
 3     int n;
 4     
 5     public int getFood(char[][] grid) {
 6         int res = Integer.MAX_VALUE;
 7         m = grid.length;
 8         n = grid[0].length;
 9         Queue<int[]> queue = new LinkedList<>();
10         for (int i = 0; i < m; i++) {
11             for (int j = 0; j < n; j++) {
12                 if (grid[i][j] == '*') {
13                     queue.offer(new int[] { i, j, 0 });
14                 }
15             }
16         }
17         
18         int[] dx = {-1, 1, 0, 0};
19         int[] dy = {0, 0, -1, 1};
20         while (!queue.isEmpty()) {
21             int[] cur = queue.poll();
22             int x = cur[0];
23             int y = cur[1];
24             int step = cur[2];
25             for (int k = 0; k < 4; k++) {
26                 int newX = x + dx[k];
27                 int newY = y + dy[k];
28                 if (newX >= 0 && newX < m && newY >= 0 && newY < n) {
29                     if (grid[newX][newY] == '#') {
30                         return step + 1;
31                     } else if (grid[newX][newY] == 'O') {
32                         grid[newX][newY] = 'X';
33                         queue.offer(new int[] { newX, newY, step + 1 });
34                     }
35                 }
36             }
37         }
38         return -1;
39     }
40 }

 

相关题目

286. Walls and Gates

542. 01 Matrix

1730. Shortest Path to Get Food

flood fill题型总结

LeetCode 题目总结

posted @ 2021-12-05 12:39  CNoodle  阅读(1171)  评论(0编辑  收藏  举报