【LetMeFly】3341.到達最后一個房間的最少時間 I:Dijkstra算法(類似深搜)-簡短清晰的話描述
力扣題目鏈接:https://leetcode.cn/problems/find-minimum-time-to-reach-last-room-i/
有一個地窖,地窖中有?n x m
?個房間,它們呈網格狀排布。
給你一個大小為?n x m
?的二維數組?moveTime
?,其中?moveTime[i][j]
?表示在這個時刻 以后 你才可以 開始?往這個房間 移動?。你在時刻?t = 0
?時從房間?(0, 0)
?出發,每次可以移動到 相鄰?的一個房間。在 相鄰?房間之間移動需要的時間為 1 秒。
請你返回到達房間?(n - 1, m - 1)
?所需要的?最少?時間。
如果兩個房間有一條公共邊(可以是水平的也可以是豎直的),那么我們稱這兩個房間是 相鄰?的。
?
示例 1:
輸入:moveTime = [[0,4],[4,4]]
輸出:6
解釋:
需要花費的最少時間為 6?秒。
- 在時刻?
t == 4
?,從房間?(0, 0)
移動到房間?(1, 0)
?,花費 1 秒。 - 在時刻?
t == 5
?,從房間?(1, 0)
?移動到房間?(1, 1)
?,花費 1?秒。
示例 2:
輸入:moveTime = [[0,0,0],[0,0,0]]
輸出:3
解釋:
需要花費的最少時間為 3?秒。
- 在時刻?
t == 0
?,從房間?(0, 0)
移動到房間?(1, 0)
?,花費 1 秒。 - 在時刻?
t == 1
?,從房間?(1, 0)
?移動到房間?(1, 1)
?,花費 1?秒。 - 在時刻?
t == 2
?,從房間?(1, 1)
移動到房間?(1, 2)
?,花費 1 秒。
示例 3:
輸入:moveTime = [[0,1],[1,2]]
輸出:3
?
提示:
2 <= n == moveTime.length <= 50
2 <= m == moveTime[i].length <= 50
0 <= moveTime[i][j] <= 109
解題方法:Dijkstra算法
使用一個數組記錄每個位置的最早到達時間(初始值除了起點為0外全是“正無窮”)。
使用一個優先隊列將所有訪問到的節點入隊,首次訪問時間最早的節點最優先。初始時將起點入隊。
接著在隊列非空時不斷將節點出隊(若已有比出隊節點訪問時間更早的解法則continue),判斷節點的4個相鄰節點,若相鄰節點能更早訪問則入隊。
- 時間復雜度 O ( n m log ? ( n m ) ) O(nm\log (nm)) O(nmlog(nm)),其中 n × m = s i z e ( m o v e T i m e ) n\times m=size(moveTime) n×m=size(moveTime),每個節點最多作為起點一次(每次出隊節點的時間總是非遞減的)。
- 空間復雜度 O ( n m ) O(nm) O(nm)
AC代碼
C++
/** @Author: LetMeFly* @Date: 2025-05-07 23:27:54* @LastEditors: LetMeFly.xyz* @LastEditTime: 2025-05-08 21:45:08*/
class Solution {
private:static constexpr int directions[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
public:int minTimeToReach(vector<vector<int>>& moveTime) {int n = moveTime.size(), m = moveTime[0].size();vector<vector<int>> ans(n, vector<int>(m, 2000000000));ans[0][0] = 0;priority_queue<tuple<int, int, int>> pq; // [<-t, x, y>, ...]pq.push({0, 0, 0});while (pq.size()) {auto [t, x, y] = pq.top();t = -t;pq.pop();for (int d = 0; d < 4; d++) {int nx = x + directions[d][0];int ny = y + directions[d][1];if (nx < 0 || nx >= n || ny < 0 || ny >= m) {continue;}int nt = max(t, moveTime[nx][ny]) + 1;if (nt < ans[nx][ny]) {ans[nx][ny] = nt;pq.push({-nt, nx, ny});}}}return ans[n - 1][m - 1];}
};
Python
'''
Author: LetMeFly
Date: 2025-05-07 23:27:54
LastEditors: LetMeFly.xyz
LastEditTime: 2025-05-07 23:49:02
'''
from typing import List
import heapqDIRECTIONS = [[0, 1], [0, -1], [1, 0], [-1, 0]]class Solution:def minTimeToReach(self, moveTime: List[List[int]]) -> int:n, m = len(moveTime), len(moveTime[0])time = [[2000000000] * m for _ in range(n)]time[0][0] = 0pq = [(0, 0, 0)]while pq:t, x, y = heapq.heappop(pq)if t > time[x][y]:continuefor dx, dy in DIRECTIONS:nx, ny = x + dx, y + dyif not(0 <= nx < n and 0 <= ny < m):continuent = max(t, moveTime[nx][ny]) + 1if nt < time[nx][ny]:time[nx][ny] = ntheapq.heappush(pq, (nt, nx, ny))return time[n - 1][m - 1]
Java
/** @Author: LetMeFly* @Date: 2025-05-07 23:27:54* @LastEditors: LetMeFly.xyz* @LastEditTime: 2025-05-08 21:56:26*/
import java.util.PriorityQueue;
import java.util.Arrays;class Solution {private final int[][] directions = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};public int minTimeToReach(int[][] moveTime) {int n = moveTime.length, m = moveTime[0].length;int[][] ans = new int[n][m];for (int i = 0; i < n; i++) {Arrays.fill(ans[i], 2000000001);}ans[0][0] = 0;PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[0] - b[0]);pq.offer(new int[]{0, 0, 0});while (!pq.isEmpty()) {int[] node = pq.poll();int t = node[0], x = node[1], y = node[2];if (t > ans[x][y]) {continue;}for (int []d : directions) {int nx = x + d[0];int ny = y + d[1];if (nx < 0 || nx >= n || ny < 0 || ny >= m) {continue;}int nt = Math.max(t, moveTime[nx][ny]) + 1;if (nt < ans[nx][ny]) {ans[nx][ny] = nt;pq.offer(new int[]{nt, nx, ny});}}}return ans[n - 1][m - 1];}
}
Golang
/** @Author: LetMeFly* @Date: 2025-05-07 23:27:54* @LastEditors: LetMeFly.xyz* @LastEditTime: 2025-05-08 22:19:42*/
package main
import "container/heap"var directions [][]int = [][]int{{0, 1}, {0, -1}, {1, 0}, {-1, 0}}func minTimeToReach(moveTime [][]int) int {n, m := len(moveTime), len(moveTime[0])ans := make([][]int, n)for i := range ans {ans[i] = make([]int, m)for j := range ans[i] {ans[i][j] = 2000000001}}ans[0][0] = 0pq := &pq3341{}heap.Init(pq)heap.Push(pq, node3341{0, 0, 0})for len(*pq) > 0 {node := heap.Pop(pq).(node3341)t, x, y := node.t, node.x, node.yif t > ans[x][y] { // 注意不能是>=,因為入隊時ans[x][y]會:=tcontinue}for _, d := range directions {nx := x + d[0]ny := y + d[1]if nx < 0 || nx >= n || ny < 0 || ny >= m {continue}nt := max(t, moveTime[nx][ny]) + 1if nt < ans[nx][ny] {ans[nx][ny] = ntheap.Push(pq, node3341{nt, nx, ny})}}}return ans[n - 1][m - 1]
}type node3341 struct {t, x, y int
}type pq3341 []node3341func (pq *pq3341) Len() int {return len(*pq)}
func (pq *pq3341) Less(i, j int) bool {return (*pq)[i].t < (*pq)[j].t}
func (pq *pq3341) Swap(i, j int) {(*pq)[i], (*pq)[j] = (*pq)[j], (*pq)[i]}
func (pq *pq3341) Push(node any) {*pq = append(*pq, node.(node3341))}
func (pq *pq3341) Pop() (ans any) {*pq, ans = (*pq)[:len(*pq) - 1], (*pq)[len(*pq) - 1]; return ans}
同步發文于CSDN和我的個人博客,原創不易,轉載經作者同意后請附上原文鏈接哦~
千篇源碼題解已開源