leetcode
leetcode 2401 ~ 2450
避免淹死并到达目的地的最短时间

避免淹死并到达目的地的最短时间

难度:

标签:

题目描述

代码结果

运行时间: 273 ms, 内存: 18.2 MB


// Leetcode 2814: 最短时间避免淹死并到达目的地
// 题目思路:
// 使用Java Stream处理相同的任务,重点在于流式处理集合数据。我们还是用Dijkstra算法,但通过流的方式管理优先队列。

import java.util.*;
import java.util.stream.*;

class Solution {
    public int minimumTimeToAvoidDrowning(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
        int[][] time = new int[m][n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; n; j++) {
                time[i][j] = Integer.MAX_VALUE;
            }
        }
        time[0][0] = grid[0][0];
        PriorityQueue<int[]> pq = new PriorityQueue<>(Comparator.comparingInt(a -> a[2]));
        pq.add(new int[]{0, 0, grid[0][0]});
        
        while (!pq.isEmpty()) {
            int[] curr = pq.poll();
            int x = curr[0], y = curr[1], t = curr[2];
            
            if (x == m - 1 && y == n - 1) {
                return t;
            }
            
            Arrays.stream(directions)
                  .map(dir -> new int[]{x + dir[0], y + dir[1]})
                  .filter(pos -> pos[0] >= 0 && pos[0] < m && pos[1] >= 0 && pos[1] < n)
                  .forEach(pos -> {
                      int nx = pos[0], ny = pos[1];
                      int newTime = Math.max(t, grid[nx][ny]);
                      if (newTime < time[nx][ny]) {
                          time[nx][ny] = newTime;
                          pq.add(new int[]{nx, ny, newTime});
                      }
                  });
        }
        
        return -1; // If no path is found
    }
}

解释

方法:

该题解使用了两个广度优先搜索(BFS)来解决问题。第一个BFS从已经被淹没的地方开始,计算每个点被淹没的时间。第二个BFS从起点开始,寻找到达终点的最短路径,同时确保在每一步行走时,该位置尚未被淹没。如果可以到达终点,则返回所需的最短时间,否则返回-1。

时间复杂度:

O(mn)

空间复杂度:

O(mn)

代码细节讲解

🦆
为什么题解中选择使用两次广度优先搜索(BFS)而不是其他算法,如深度优先搜索(DFS)或迪杰斯特拉算法?
题解选择使用两次广度优先搜索(BFS)主要是因为BFS能够有效地找到从一点到另一点的最短路径,这在本题中非常关键。第一个BFS用于确定每个位置被淹没的时间,保证计算的是从最初的水源开始的全局最短淹没时间。第二个BFS用于寻找在不被淹没的情况下,从起点到终点的最短路径。使用DFS可能会导致过早探索深层节点,无法保证找到的是最短路径。而迪杰斯特拉算法在这里不是特别适用,因为它主要解决带权重的最短路径问题,而本题中每一步的权重相同,且需要额外考虑时间限制(淹没时间),这使得BFS成为更合适的选择。
🦆
题解中没有明确说明如何处理边界条件,比如起点或终点已被初始淹没的情况,这种情况下算法的输出是什么?
题解中确实没有明确说明处理这些特殊边界条件的细节。在实际实现中,如果起点'S'已经在初始状态被淹没(例如起点就在'*'处或者被立即淹没的地方),则无法开始正常的路径搜索,应该立即返回-1,表示无法到达目的地。同样,如果终点'D'在开始搜索之前已被淹没,也应返回-1。这些情况需要在算法开始前进行检查,以确保输入数据的有效性和搜索的可行性。
🦆
在代码实现中,变量`t`在第一个BFS和第二个BFS中有不同的作用和含义,请问这种设计有什么特别的考虑吗?
在代码中,变量`t`被用于两个不同的目的确实是一种特别的设计考虑。在第一个BFS中,`t`表示时间,用来记录地图上每个点被淹没的时间。这样可以确保在第二个BFS进行时,每一步移动都能检查该点是否已被淹没。在第二个BFS中,`t`被用作反向时间计数器,用于跟踪从起点到当前点的步数(即时间)。使用单个变量来表示不同的时间概念(淹没时间和移动时间),简化了代码的复杂性,同时也有效地利用了变量来控制算法的流程。

相关问题