1. 程式人生 > 其它 >1584. 連線所有點的最小費用

1584. 連線所有點的最小費用

技術標籤:演算法題解python演算法leetcode

1584. 連線所有點的最小費用

題目

給你一個points 陣列,表示 2D 平面上的一些點,其中 points[i] = [xi, yi] 。

連線點 [xi, yi] 和點 [xj, yj] 的費用為它們之間的 曼哈頓距離 :|xi - xj| + |yi - yj| ,其中 |val| 表示 val 的絕對值。

請你返回將所有點連線的最小總費用。只有任意兩點之間 有且僅有 一條簡單路徑時,才認為所有點都已連線。

示例 1:c

輸入:points = [[0,0],[2,2],[3,10],[5,2],[7,0]]
輸出:20
解釋:

我們可以按照上圖所示連線所有點得到最小總費用,總費用為 20 。
注意到任意兩個點之間只有唯一一條路徑互相到達。

解析

對於這道題來說,需要用最小生成樹的方法來解決,這裡採用Kruskal演算法並且用並查集的方法判斷圖中節點的連通性,保證兩點之間有且僅有一條邊

Kruskal演算法

將任意兩節點的距離得出,並且按照從小到大的順序排序,然後根據節點距離依次將兩點連線,此題樹的根節點可以隨意選擇,我將第一個點設定為這個最小生成樹的根節點,其實就是使用貪心的方法

from typing import List

class DisjointSetUnion:
    def __init__(self,
n): self.n = n self.rank = [1]*n# 用來判斷節點級別,確認根節點 self.f = list(range(n)) def find(self, x: int) -> int: if self.f[x] == x: return x self.f[x] = self.find(self.f[x]) return self.f[x] def unionSet(self, x: int, y: int) -> bool
: fx,fy = self.find(x), self.find(y) if fx == fy: # 若父節點一致,則這兩個節點不能相連 return False if self.rank[fx] < self.rank[fy]: fx, fy = fy, fx self.rank[fx] += self.rank[fy] self.f[fy] = fx # 將級別低的點併入級別高的父節點中 return True class Solution: def minCostConnectPoints(self, points: List[List[int]]) -> int: dist = lambda x,y : abs(points[x][0] - points[y][0])+abs(points[x][1] - points[y][1]) n = len(points) dsu = DisjointSetUnion(n) edges = [] # 得出圖中任意兩點的邊的集合 for i in range(n): for j in range(i+1,n): edges.append((dist(i,j),i,j)) edges.sort() ret,num = 0,1 for lengh,x,y in edges: if dsu.unionSet(x,y):# 使用並查集維護連通性,若當前邊兩端不連通即可選擇這條邊 ret += lengh num += 1 if num == n: break return ret

收穫

  • 學習了最小生成樹演算法,瞭解了並查集

  • 學習了python中lambda表示式

    可以使用lambda關鍵字建立匿名函式。Lambda函式可以在需要函式物件的任何地方使用。它們在語法上限於單個表示式。所謂匿名就是無名。

    例如定義兩個加法:

    func =lambda a,b: a+b
    
    print func(4,2)
    

    輸出:

    6