LeetCode每日一题,778. Swim in Rising Water
先看题目描述
大意就是给定一个 grid,grid[i][j] 代表该位置的高度,水位会随着时间上升,时间 t 时水位为 t,若我们想从一个位置游到某相邻位置,只有当水位 t 不低于当前位置和相邻位置的高度才可以,我们可以瞬间移动无限距离,问想从左上角游到右下角,最低的水位是多少
算法和思路
这题实际上和昨天的题 最小体力消耗路径 是一样的,也是要把这个二维矩阵给抽象成图,只是对边的长度的计算方式不同,昨天的题和今天的题本质是一样的,昨天的题有三种算法可以解决,今天的题也同样
二分查找
可以使用二分查找定位到最短等待时间。具体来说:由于题目限制了 grid[i][j] 的范围,所以可以在区间 [0, N * N - 1] 里猜一个整数,针对这个整数从起点(左上角)开始做一次深度优先遍历或者广度优先遍历
- 当小于等于该数值时,如果存在一条从左上角到右下角的路径,说明答案可能是这个数值,也可能更小;
- 当小于等于该数值时,如果不存在一条从左上角到右下角的路径,说明答案一定比这个数值更大。
按照这种方式不断缩小搜索的区间,最终找到最少等待时间
并查集
我们可以将这 N * N 个节点放入并查集中,实时维护它们的连通性
对于 grid[i][j] 和其相邻方格 grid[i][j + 1],我们认为其之间存在一条边,长度为 max{grid[i][j],grid[i][j + 1]},对于其他相邻方格也均是类似处理。因此我们可以将所有边按照长度进行升序排列,然后依次将边添加入并查集中,并将该边的两顶点所属连通分量合并,每次判断左上角和右下角是否连通,若一旦连通,那么刚刚添加的边的长度就是我们要找的答案
*Dijkstra算法 *
注意这个问题求的是从一个源点到目标顶点的最短路径,并且这条路径上的边没有负数(这一点非常重要,单元格的高度大于等于 0),符合 Dijkstra 算法的应用场景。为此我们可以把问题抽象成一个带权有向图,权值是有向边指向的顶点的高度
算法源码
二分查找
这题使用二分查找的效率是最高的,因为题目限定了 grid[i][j] 的值范围为 [0,N * N - 1],这样二分查找的初始范围就比较小,运行时间比较短,而昨天的题里面,二分查找的初始范围比较大,运行时间比较长,效率相对来说就低些
下面是题解的 二分查找 + DFS 的代码
1 | public class Solution { |
下面是题解的 二分查找 + BFS 的代码
1 | public class Solution { |
并查集
这题我第一反应就是使用并查集,基本就是套用的昨天写的并查集算法的代码的模板,下面是自己实现的代码
1 | class Solution { |
Dijkstra 算法
下面是题解的 Dijkstra 算法的代码,里面使用到了最小堆,用于每次迭代时寻找 距离向量最小的未访问节点
1 | public class Solution { |