力扣 leetode 778. 水位上升的泳池中游泳 (python)
技術標籤:pythonleetcode演算法pythonleetcode並查集
Topic
在一個 N x N 的座標方格 grid 中,每一個方格的值 grid[i][j] 表示在位置 (i,j) 的平臺高度。
現在開始下雨了。當時間為 t 時,此時雨水導致水池中任意位置的水位為 t 。你可以從一個平臺遊向四周相鄰的任意一個平臺,但是前提是此時水位必須同時淹沒這兩個平臺。假定你可以瞬間移動無限距離,也就是預設在方格內部遊動是不耗時的。當然,在你游泳的時候你必須待在座標方格里面。
你從座標方格的左上平臺 (0,0) 出發。最少耗時多久你才能到達座標方格的右下平臺 (N-1, N-1)?
Example_1
輸入: [[0,2],[1,3]]
輸出: 3
解釋:
時間為0時,你位於座標方格的位置為 (0, 0)。
此時你不能遊向任意方向,因為四個相鄰方向平臺的高度都大於當前時間為 0 時的水位。
等時間到達 3 時,你才可以遊向平臺 (1, 1). 因為此時的水位是 3,座標方格中的平臺沒有比水位 3 更高的,所以你可以遊向座標方格中的任意位置
Example_2
輸入: [[0,1,2,3,4],[24,23,22,21,5],[12,13,14,15,16],[11,17,18,19,20],[10,9,8,7,6]]
輸出: 16
解釋:
0 1 2 3 4
24 23 22 21 512 13 14 15 16
11 17 18 19 20
10 9 8 7 6
最終的路線用加粗進行了標記。
我們必須等到時間為 16,此時才能保證平臺 (0, 0) 和 (4, 4) 是連通的
Tips
2 <= N <= 50.
grid[i][j] 是 [0, …, N*N - 1] 的排列。
Solution
本思路與昨天題目思路相似
可以參考leetcode 1631. 最小體力消耗路徑
並查集程式碼基於 基於列表的並查集實現模板實現
Kruskal演算法詳解
本題我們還是運用類Kruskal演算法
整體思路上我們利用並查集
來判斷第一個點和最後一個點是否連通
從而判斷能否到達
每當水位上升一
我們就有一些點可以到達
第一步 計算權重
在本題中權重可以類似於1631題
將其看作相鄰位置平臺水位的較大值
之後將grid變為[邊的開始節點, 邊的結束節點, 權重]的形式
第二步 按照權重排序
按照權重從小到大排序
第三步 併入邊
初始化一個並查集uf
將邊按權重從小到大順序連通
如果第一個節點與最後一個節點連通
則輸出當前邊的權重即為結果
Code
class UnionFind:
def __init__(self, n):
self.father = list(range(n))
self.size = [1] * n
self.n = n
def find(self, x):
if self.father[x] == x:
return x
self.father[x] = self.find(self.father[x])
return self.father[x]
def merge(self, x, y):
x, y = self.find(x), self.find(y)
if x == y:
return False
if self.size[x] < self.size[y]:
x, y = y, x
self.father[y] = x
self.size[x] += self.size[y]
def is_connected(self, x, y):
return self.find(x) == self.find(y)
class Solution:
def swimInWater(self, grid: List[List[int]]) -> int:
total = []
m, n = len(grid), len(grid[0])
for i in range(m):
for j in range(n):
if i < m - 1:
total.append([i * n + j, (i + 1) * n + j, max(grid[i][j], grid[i+1][j])])
if j < n - 1:
total.append([i * n + j, i * n + j + 1, max(grid[i][j], grid[i][j+1])])
uf = UnionFind(m * n)
total.sort(key=lambda x:x[2])
res = 0
for edge in total:
if uf.find(edge[0]) != uf.find(edge[1]):
uf.merge(edge[0],edge[1])
res = max(res, edge[-1])
if uf.find(0) == uf.find( m * n - 1):
return res