LeetCode題解(0407):接雨水II(Python)

長行發表於2020-11-20

題目:原題連結(困難)

標籤:堆、廣度優先搜尋

解法時間複雜度空間複雜度執行用時
Ans 1 (Python) O ( N M l o g ( N + M ) ) O(NMlog(N+M)) O(NMlog(N+M)) O ( N + M ) O(N+M) O(N+M)144ms (80.58%)
Ans 2 (Python)
Ans 3 (Python)

解法一(海平面上升思路):

class Solution:
    def trapRainWater(self, heightMap: List[List[int]]) -> int:
        # 判斷位置是否有效
        def is_valid(x, y):
            return 0 <= x < s1 and 0 <= y < s2

        # 海平面不斷升高淹沒盆地思路
        s1, s2 = len(heightMap), len(heightMap[0])
        s = s1 * s2

        # 處理池子過小的情況
        # O(1)
        if s1 <= 2 or s2 <= 2:
            return 0

        # 計算最外層堤壩位置
        # O(M+N)
        wall_list = []
        for i1 in range(0, s1):
            wall_list.append((i1, 0))
            wall_list.append((i1, s2 - 1))
        for i2 in range(0, s2):
            wall_list.append((0, i2))
            wall_list.append((s1 - 1, i2))

        # 處理最外層堤壩高度
        visited = set()
        heap = []
        for i1, i2 in wall_list:
            heap.append((heightMap[i1][i2], i1, i2))
            visited.add((i1, i2))

        # 使最外層堤壩高度具有堆的特徵
        heapq.heapify(heap)

        # 初始化海平面高度
        now_height = 0

        # 開始提升海平面高度直至只剩下狹長(中間不包括被堤壩包圍的陸地)島嶼
        ans = 0
        while len(visited) < s:
            # 從堤壩高度堆中取出最低的堤壩
            height, i1, i2 = heapq.heappop(heap)

            # 升高(或不用升高)海平面至可以淹沒堤壩的高度
            now_height = max(now_height, height)

            # 計算堤壩周圍的座標位置
            neighbours = [(i1 + 1, i2), (i1 - 1, i2), (i1, i2 + 1), (i1, i2 - 1)]

            # 計算堤壩周圍的非堤壩或海洋位置(腹地位置)
            inners = [neighbour for neighbour in neighbours if
                      (is_valid(neighbour[0], neighbour[1]) and neighbour not in visited)]

            # 檢查腹地位置的淹沒情況
            for ii1, ii2 in inners:
                # 如果腹地位置比當前海平面低,則可以增加積水量
                if heightMap[ii1][ii2] < now_height:
                    ans += now_height - heightMap[ii1][ii2]

                # 將當前腹地位置作為新的堤壩
                heapq.heappush(heap, (heightMap[ii1][ii2], ii1, ii2))
                visited.add((ii1, ii2))

        return ans

相關文章