题目:
给你一个points 数组,表示 2D 平面上的一些点,其中 points[i] = [xi, yi] 。
连接点 [xi, yi] 和点 [xj, yj] 的费用为它们之间的 曼哈顿距离 :|xi - xj| + |yi - yj| ,其中 |val| 表示 val 的绝对值。
请你返回将所有点连接的最小总费用。只有任意两点之间 有且仅有 一条简单路径时,才认为所有点都已连接。
思路:
标准的最小生成树, Minimum Spanning Trees
两点间的权重值就是曼哈顿距离,
然后 MST, 把每条边的值加起来
常用两种算法:
普里姆算法, Prim 和克鲁斯克尔算法 Kruskal
- Prim, 从一个点出发,去找其最小边,
再从已连通点出发,保证不成环的情况下,去找此时未连上的最小边
- Kruskal,把所有边的权重值从小到大排,
从最小边出发,保证不成环的情况下,去找此时未连上的最小边
下面使用 Kruskal,保证不成环,使用并查集
并查集两个操作,查找与合并, Union 和 Find
建立映射,使用 0 到 n - 1 的数组,代表 n 个点,
连一条边,就合并一次
合并就是,代表的数组上的两个值, x = y
还有一个寻根操作
代码:
class Solution{
struct Distance {
let from: Int
let to: Int
let len: Int
}
var par: [Int]!
func minCostConnectPoints(_ points: [[Int]]) -> Int {
var map = [Distance]()
let rowCount = points.count
guard rowCount > 1 else {
return 0
}
var i = 0
while i < rowCount {
var j = i + 1
while j < rowCount {
let val = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
map.append(Distance(from: i, to: j, len: val))
j += 1
}
i += 1
}
par = Array(0..<rowCount)
var result = 0
i = 0
let lookup = map.sorted { (lhs, rhs) -> Bool in
lhs.len < rhs.len
}
let count = lookup.count
while i < count {
let u = lookup[i].from, v = lookup[i].to, x = find(val: u), y = find(val: v)
if x != y{
par[x] = y
result += lookup[i].len
}
i += 1
}
return result
}
func find(val x: Int) -> Int{
if x == par[x]{
return x
}
else{
par[x] = find(val: par[x])
return par[x]
}
}
}