LeetCode每日一题(1584. Min Cost to Connect All Points)

本文介绍如何使用Prim算法解决给定二维坐标点集的最小连接问题,通过曼哈顿距离计算连接成本,实现所有点间的唯一路径连接。涉及MST概念及Prim算法的应用实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.

这题涉及到一个 MST(Minimum Spanning Tree)的概念

A minimum spanning tree (MST) or minimum weight spanning tree is a subset of the edges of a connected, edge-weighted undirected graph that connects all the vertices together, without any cycles and with the minimum possible total edge weight.

以上是 MST 的定义, 理解起来不难, 创建 MST 的方式有很多种, 教程里面描述了两种, 一种叫 Kruskal’s Algorithm, 另一种叫 Prim’s algorithm, 我都看了一下, 发觉对我来说 Prim’s algorithm 更简单一些, 于是就选择用这种方式来解, 主要步骤如下:

  1. 先根据points来创建每一个点到其他任意一点的变并计算出距离
  2. 任意取出一点作为树的根节点, 从这一点开始每次找到离该点最近的点加入到树中, 并且将所加入的点的关联的边都加入到待检查的边当中。如果所要加入的点已经存在于树中了, 则略过去寻找下一个最近的点
  3. 当树有了 n-1 个边的时候(n 为points的数量), 退出循环

use std::cmp::Reverse;
use std::collections::BinaryHeap;

impl Solution {
    pub fn min_cost_connect_points(points: Vec<Vec<i32>>) -> i32 {
        let mut edges = vec![BinaryHeap::new(); points.len()];
        for i in 0..points.len() {
            for j in i + 1..points.len() {
                let pi = points[i].clone();
                let pj = points[j].clone();
                let dist = (pi[0] - pj[0]).abs() + (pi[1] - pj[1]).abs();
                edges[i].push(Reverse((dist, j)));
                edges[j].push(Reverse((dist, i)));
            }
        }
        let mut visited = vec![false; points.len()];
        let mut count = 0;
        let mut ans = 0;
        let mut stack = edges[0].clone();
        visited[0] = true;
        'outer: while count < points.len() - 1 {
            while let Some(Reverse((dist, i))) = stack.pop() {
                if visited[i] {
                    continue 'outer;
                }
                visited[i] = true;
                count += 1;
                ans += dist;
                stack.append(&mut edges[i].clone());
                continue 'outer;
            }
        }
        ans
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值