news 2026/6/10 13:23:57

LeetCode 1584. 连接所有点的最小费用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LeetCode 1584. 连接所有点的最小费用

问题

给定一个二维数组points,其中points[i] = [xi, yi]表示平面上的一个点。

连接两个点[xi, yi][xj, yj]的费用为它们之间的曼哈顿距离:

|xi - xj| + |yi - yj|

要求把所有点都连接起来,并且任意两个点之间都可以通过若干条边互相到达。返回连接所有点所需要的最小总费用。

示例 1:

输入:points = [[0,0],[2,2],[3,10],[5,2],[7,0]]
输出:20
解释:用最小费用连接所有点,总费用为20

示例 2:

输入:points = [[3,12],[-2,5],[-4,1]]
输出:18

思路

首先这道题的直觉解法很明显:既然要让所有点都连通,那我们可以在点和点之间连边。任意两个点之间都能连一条边,边权就是它们的曼哈顿距离。

那问题就变成了:在一个完全图里,选择一些边,让所有点连通,并且总费用最小。

如果随便连边,很容易多连出一些没必要的边。因为只要所有点能互相到达就够了,不需要每两个点之间都直接连边。对于n个点来说,真正需要的边数其实是n - 1条。

那是不是可以把问题转化成“最小生成树”?也就是在所有能连接全部节点的方案中,找出边权总和最小的一棵树。

怎么构造这棵最小生成树?可以想到 Prim 算法。

Prim 的想法是:先从任意一个点开始,把它当成当前已经连好的树。然后每次从还没加入树的点里,选择一个“接入当前树代价最小”的点加入进来。不断重复,直到所有点都加入树。

拿变量来说,minDist[i]表示点i接入当前这棵树的最小费用。

一开始只有点0在树里,所以:

minDist[0] = 0 其他点 minDist = INT_MAX

每次选出未访问点中minDist最小的那个点u,把它加入树,并把这次接入费用加到答案里。

那加入u后,为什么要更新其他点的minDist

因为u成了树的一部分,其他还没加入树的点,现在除了可以通过原来的树中节点接入,也可以通过u接入。于是对每个未访问点x,计算ux的曼哈顿距离,如果这个距离更小,就更新minDist[x]

不难发现,这个过程就是一直选择当前最便宜的连接方式,把一个新点接入已经形成的树里。等所有点都加入后,得到的总费用就是最小连接费用。

解决

  1. 先定义几个关键变量。

    minDist[i] 表示点 i 接入当前生成树的最小费用 visited[i] 表示点 i 是否已经加入生成树 res 表示当前总费用

    一开始选择点0作为起点,所以设置:

    minDist[0] = 0
  2. 循环n次,每次向生成树中加入一个点。

    在所有还没访问过的点里,找到minDist最小的点u

    !visited[j] && minDist[j] 最小

    这个点就是当前接入生成树代价最小的点。

  3. 把点u加入生成树。

    标记:

    visited[u] = true

    并把它的接入费用加入答案:

    res += minDist[u]
  4. 更新其他未访问点的最小接入费用。

    对于每个还没加入生成树的点x,计算它和u之间的曼哈顿距离:

    abs(points[u][0] - points[x][0]) + abs(points[u][1] - points[x][1])

    如果通过u接入更便宜,就更新minDist[x]

注意:这里不需要提前把所有边存下来。因为任意两个点之间的距离都可以直接通过坐标计算出来,所以每次加入新点后,现场计算并更新即可。

classSolution{public:intminCostConnectPoints(vector<vector<int>>&points){intn=points.size();vector<int>minDist(n,INT_MAX);vector<bool>visited(n,false);intres=0;minDist[0]=0;for(inti=0;i<n;++i){intu=-1;for(intj=0;j<n;++j){if(!visited[j]&&(u==-1||minDist[j]<minDist[u])){u=j;}}visited[u]=true;res+=minDist[u];for(intx=0;x<n;++x){if(!visited[x]){intdist=abs(points[u][0]-points[x][0])+abs(points[u][1]-points[x][1]);if(minDist[x]>dist){minDist[x]=dist;}}}}returnres;}};

时间复杂度为O(n^2),因为每次选点需要遍历所有点,更新距离也需要遍历所有点;空间复杂度为O(n),主要用于minDistvisited数组。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 13:19:52

网友的一个SQL问题

起因网友问在一个大表里 [工艺名称] like %抛% 是否能优化俺的回答是 这个工艺名称 是否有数据字典&#xff0c;如果有数据字典就可以优化分析写在分析前其实erp his 等这些mis 系统一般在开发时都是先开发数据字典部分。like %抛% &#xff0c;索引很难有效果&#xff0c…

作者头像 李华
网站建设 2026/6/10 13:17:15

浏览器市场分析-大屏静态布局制作

浏览器市场分析-大屏静态布局制作1 实验目的本实验基于《浏览器市场与用户画像分析-数据加工》产出的各项统计表&#xff0c;使用助睿Max数据大屏制作浏览器市场行为分析大屏。通过本实验&#xff0c;学生应掌握&#xff1a;2 实验环境实验平台&#xff1a;助睿在线实验平台 ht…

作者头像 李华
网站建设 2026/6/10 13:16:27

监控iOS设备性能的工具Perfdog:特点、使用步骤与代码示例

监控iOS设备性能的工具&#xff1a;Perfdog 在移动应用开发过程中&#xff0c;性能监控是一个非常重要的环节。Perfdog是一款专门针对iOS设备进行性能监控的工具&#xff0c;它可以帮助开发者及时发现并解决应用性能问题&#xff0c;提高应用的用户体验。 Perfdog的特点 Perfdo…

作者头像 李华
网站建设 2026/6/10 13:11:00

sendgrid-python:用 Python 调用 SendGrid 邮件 API

文章目录sendgrid-python&#xff1a;用 Python 调用 SendGrid 邮件 API1、这项目是干嘛的2、安装和配置3、发一封邮件有多简单4、不止能发邮件5、适合哪些人用sendgrid-python&#xff1a;用 Python 调用 SendGrid 邮件 API sendgrid-python 在 GitHub 上已经拿到 1,628 Star…

作者头像 李华