1. 程式人生 > 其它 >力扣 leetode 778. 水位上升的泳池中游泳 (python)

力扣 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 5

12 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

Result

在這裡插入圖片描述