1584. 連線所有點的最小費用
阿新 • • 發佈:2021-01-20
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