1584-min-cost-to-connect-all-points¶
Try it on leetcode
Description¶
You are given an array points representing integer coordinates of some points on a 2D-plane, where points[i] = [xi, yi].
The cost of connecting two points [xi, yi] and [xj, yj] is the manhattan distance between them: |xi - xj| + |yi - yj|, where |val| denotes the absolute value of val.
Return the minimum cost to make all points connected. All points are connected if there is exactly one simple path between any two points.
Example 1:
Input: points = [[0,0],[2,2],[3,10],[5,2],[7,0]] Output: 20 Explanation:We can connect the points as shown above to get the minimum cost of 20. Notice that there is a unique path between every pair of points.
Example 2:
Input: points = [[3,12],[-2,5],[-4,1]] Output: 18
Constraints:
1 <= points.length <= 1000-106 <= xi, yi <= 106- All pairs
(xi, yi)are distinct.
Solution(Python)¶
class UnionFind:
def __init__(self, size):
self.group = [0] * size
self.rank = [0] * size
for i in range(size):
self.group[i] = i
def find(self, a):
if a != self.group[a]:
self.group[a] = self.find(self.group[a])
return self.group[a]
def union(self, a, b):
groupA = self.find(a)
groupB = self.find(b)
if groupA == groupB:
return False
if self.rank[groupA] > self.group[groupB]:
self.group[groupB] = groupA
elif self.rank[groupB] > self.group[groupA]:
self.group[groupA] = groupB
else:
self.group[groupB] = groupA
self.rank[groupA] += 1
return True
def isconnected(self, a, b):
return self.find(a) == self.find(b)
class Solution:
def minCostConnectPoints(self, points: List[List[int]]) -> int:
return self.optimized_prims(points)
# Time Complexity: O(n2 log(n))
# space complexity: o(n^2)
def kruskar(self, points: List[List[int]]) -> int:
n = len(points)
all_edges = []
for cur_node in range(n):
for next_node in range(cur_node + 1, n):
weight = abs(points[cur_node][0] - points[next_node][0]) + abs(
points[cur_node][1] - points[next_node][1]
)
all_edges.append((weight, cur_node, next_node))
all_edges.sort()
uf = UnionFind(n)
mst_cost = 0
edges_used = 0
for w, p1, p2 in all_edges:
if uf.union(p1, p2):
mst_cost += w
edges_used += 1
if edges_used == n - 1:
break
return mst_cost
# Time Complexity: O(n2 log(n))
# space complexity: o(n^2)
def naiveprims(self, points: List[List[int]]) -> int:
n = len(points)
heap = [(0, 0)]
in_mst = [False] * n
mst_cost = 0
edges_used = 0
while edges_used < n:
weight, cur_node = heapq.heappop(heap)
if in_mst[cur_node]:
continue
in_mst[cur_node] = True
mst_cost += weight
edges_used += 1
for next_node in range(n):
if not in_mst[next_node]:
next_weight = self.manhattan_dist(
points[cur_node], points[next_node]
)
heapq.heappush(heap, (next_weight, next_node))
return mst_cost
def manhattan_dist(self, point1, point2):
return abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])
# Time Complexity: O(n^2)
# space complexity: o(n)
def optimized_prims(self, points: List[List[int]]) -> int:
n = len(points)
mst_cost = 0
edges_used = 0
in_mst = [False] * n
min_dist = [math.inf] * n
min_dist[0] = 0
while edges_used < n:
cur_min_edge = math.inf
cur_node = -1
for node in range(n):
if not in_mst[node] and cur_min_edge > min_dist[node]:
cur_min_edge = min_dist[node]
cur_node = node
mst_cost += cur_min_edge
edges_used += 1
in_mst[cur_node] = True
for next_node in range(n):
weight = self.manhattan_dist(
points[cur_node], points[next_node])
if not in_mst[next_node] and min_dist[next_node] > weight:
min_dist[next_node] = weight
return mst_cost
We can connect the points as shown above to get the minimum cost of 20.
Notice that there is a unique path between every pair of points.