并查集的延伸--克鲁斯卡尔法求最小生成树MST

并查集的延伸--克鲁斯卡尔法求最小生成树MST

  • 力扣 1135 力扣 1584
  • 并查集 UnionFind.java

力扣 1135 力扣 1584

package com.caoii;/**@program:labu-pratice-study*@package:com.caoii*@author: Alan*@Time: 2024/4/14  9:09*@description: 最小生成树相关题目测试*/import org.junit.jupiter.api.Test;import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;public class MstTest {/*力扣1135想象一下你是个城市基建规划者,地图上有 n 座城市,它们按以 1 到 n 的次序编号。给你整数 n 和一个数组 conections,其中 connections[i] = [xi, yi, costi]表示将城市 xi 和城市 yi 连接所要的costi(连接是双向的)。返回连接所有城市的最低成本,每对城市之间至少有一条路径。如果无法连接所有 n 个城市,返回 -1 该最小成本 应该是所用全部连接成本的总和*/static class Node {int xi;int yi;int costi;Node(int xi, int yi, int costi) {this.xi = xi;this.yi = yi;this.costi = costi;}}public int minimumCost(int n, int[][] connections) {int sum = 0;if (connections.length < n - 1) {return -1;// 具备链接条件的边 小于 n-1 条 则无法形成 最小生成树}ArrayList<Node> nodeArrayList = new ArrayList<Node>();for (int[] connection : connections) {Node node = new Node(connection[0], connection[1], connection[2]);nodeArrayList.add(node);}// 按 costi 的值 给 list 排序nodeArrayList.sort(new Comparator<Node>() {@Overridepublic int compare(Node o1, Node o2) {return o1.costi - o2.costi;}});// 测试排序/*for (Node node : nodeArrayList) {System.out.println(node.xi + " " + node.yi + " " + node.costi);}*/UnionFind unionFind = new UnionFind(n + 1);for (Node node : nodeArrayList) {if (!unionFind.connected(node.xi, node.yi)) {unionFind.union(node.xi, node.yi);sum += node.costi;if (unionFind.count() == 2) {return sum;}}}if (unionFind.count() == 2) {return sum;} else {return -1;}}@Testpublic void test_01() {int n = 4;int connections[][] = new int[][]{{1, 2, 3},{3, 4, 4},};System.out.println(minimumCost(n, connections));}/*力扣1584* 给你一个points 数组,表示 2D 平面上的一些点,其中 points[i] = [xi, yi] 。连接点 [xi, yi] 和点 [xj, yj] 的费用为它们之间的 曼哈顿距离 :|xi - xj| + |yi - yj| ,其中 |val| 表示 val 的绝对值。请你返回将所有点连接的最小总费用。只有任意两点之间 有且仅有 一条简单路径时,才认为所有点都已连接*/public int minCostConnectPoints(int[][] points) {ArrayList<Node> nodeArrayList = new ArrayList<Node>();for (int i = 0; i < points.length; i++) {for (int j = i + 1; j < points.length; j++) {int costi = Math.abs(points[i][0] - points[j][0]) + Math.abs(points[i][1] - points[j][1]);Node node = new Node(i, j, costi);nodeArrayList.add(node);}// i j 的取值范围 在 0到(n-1) 之间// 此时取到了 任意两个顶点之间相连的 所有边// 不存在找不出 生成树的情况 故而不需要判断 M 是否小于 N-1}// 按照costi 升序排序Collections.sort(nodeArrayList, Comparator.comparingInt((Node a) -> a.costi));/*// 测试排序结果for (Node node : nodeArrayList) {System.out.println(node.xi + " " + node.yi + " " + node.costi);}System.out.println();// 按照costi 降序排序//通过显式指定参数类型,可以帮助编译器更好地理解Lambda表达式Collections.sort(nodeArrayList, Comparator.comparingInt((Node a) -> a.costi).reversed());for (Node node : nodeArrayList) {System.out.println(node.xi + " " + node.yi + " " + node.costi);}*/int n = points.length;int sum = 0;UnionFind unionFind = new UnionFind(n);for (Node node : nodeArrayList) {if (!unionFind.connected(node.xi, node.yi)) {unionFind.union(node.xi, node.yi);sum += node.costi;if (unionFind.count() == 1) {// 只剩一个连通分量 循环结束return sum;}}}// 不存在找不出 生成树的情况 故而不需要在循环结束后再判断 是否还剩唯一一个连通分量return sum;}@Testpublic void test_02() {int[][] points = new int[][]{{0, 0}, {2, 2}, {3, 10}, {5, 2}, {7, 0}};System.out.println(minCostConnectPoints(points));}
}

并查集 UnionFind.java

package com.caoii;/**@program:labu-pratice-study*@package:com.caoii*@author: Alan*@Time: 2024/4/12  21:53*@description: 并查集的实现*/public class UnionFind {// 记录连通分量private int count;// 节点X的父节点 是 parent[x]private int[] parent;//使用一个size数组  记录每棵树包含的节点数目//来让两个树合并的时候尽量让小的树接到大的树的下面//这样每次使用find向上找根节点的复杂度能相对减少//private int[] size;// 通过改造find函数 可将每个树都变成 真正高度为2// 即 每个子节点都直接与最高根节点相连的样式// 故size就不必再使用了// 构造函数 n 为 图的节点数目public UnionFind(int n) {this.count = n;// 一开始互不连通 则 连通分量的数目等于节点数目parent = new int[n];// 父节点指针初始时指向自己for (int i = 0; i < n; i++) {parent[i] = i;//size[i] = 1;}// 若两个节点被连通 则其中任意一个节点的根节点指针指向另一个节点}/*将p和q 所在的连通分量进行 链接*/public void union(int p, int q) {int rootP = find(p);int rootQ = find(q);// find方法获取两个树的最高根节点if (rootP == rootQ) {// 两棵树已经连通则最高根节点一定相同// 不需要 再次链接 直接退出方法return;}/*改进find之后不用size了//两棵树最高根节点不同的时候://两棵树合并为一棵树  设置P的根节点为Qif (size[rootP] > size[rootQ]) {parent[rootQ] = rootP;size[rootP] += size[rootQ];// P树更高 则 把 Q树接在P树下面,让Q的父节点指针指向P// P的高度增加// 实际上此时所说的高度不是真的高度而是该树的全部节点个数} else {parent[rootP] = rootQ;size[rootQ] += size[rootP];}*///两棵树最高根节点不同的时候://两棵树合并为一棵树  设置P的根节点为Qparent[rootP] = rootQ;count--;// 两个分量合二为一   分量数目减一}/*返回某个节点X的最高根节点*/public int find(int x) {/*传统方法  逐次向上寻找最高根节点while (parent[x] != x) {x = parent[x];}return x;// 若根节点指针指向自己,则返回自己// 若根节点指针没有指向自己,则把根节点指针指向的元素赋值给X 并循环判断// 若 3-->5-->6  则 X=3时执行:x=5 ——> 5!=parent[5]=6 ——> x=6 ——> 6=parent[6]=6 ——> return 6*/// 改进方法 在寻找最高根节点的过程中// 将树构造为 真实高度为2 所有子节点都与根节点直接相连的形式:if (parent[x] != x) {// x的根节点 不是 x 自己// 则x 存在根节点parent[x] = find(parent[x]);// 递归运算// 最后:}return parent[x];// 递归出口: 递归到最高层根节点 此时 x==parent[x] 所以返回x// 则 次高层处节点为y,  parent[y] = find(parent[y]) = x// 即次高层处节点的父指针指向最高节点// 同理 次次高层处节点为z,  parent[z] = find(parent[z]) = find(y) = parent[y] = x// 即次次高层处节点的父指针指向最高节点x// 以此类推// 最后结果就是所有子节点都直接与根节点直接相连  树的真是高度为2}/*判断 p 和 q 是否连通*/public boolean connected(int p, int q) {int rootP = find(p);int rootQ = find(q);return rootP == rootQ;// 若两个树的最高节点相同则p与q连通}/*返回图中有多少个连通分量*/public int count() {return count;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/814746.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Terminal 美化

摘自&#xff1a;Mac 系统终端美化与 ZSH 多设备配置同步共享 个人对 iTerm2 等第三方终端工具不太感冒&#xff0c;一直在用系统内置终端。 相比之下&#xff0c;系统自带的 Terminal 可谓是简陋啊。 安装了 Oh My Zsh&#xff0c;加上一些插件&#xff0c;感觉还行。 再调…

如何防止软件过度封装和抽象?

一、合适的软件架构 构建可读性强、高内聚、低耦合的软件架构是软件工程中的重要原则&#xff0c;这有助于提高代码的维护性、扩展性和复用性。以下是一些实践方法&#xff1a; 1. **模块化设计**&#xff1a;将系统划分为一系列职责单一、功能明确的模块或组件&#xff0c;每…

ELK企业级日志分析系统以及多种部署

目录 ELK简介 ELK简介 ELK平台是一套完整的日志集中处理解决方案&#xff0c;将 ElasticSearch、Logstash 和 Kiabana 三个开源工具配合使用&#xff0c; 完成更强大的用户对日志的查询、排序、统计需求。 ●ElasticSearch&#xff1a;是基于Lucene&#xff08;一个全文检索引…

windows应急中的快捷键

windows应急中的快捷键 应急的时候&#xff0c;快捷键很重要&#xff0c;记录一下windows主机排查需要用到的快捷键 windows快捷键 appwiz.cpl 是打开安装面板 程序和功能 控制面板程序和功能 搜索程序和功能 控制而板主页 卸载或更改程序 若要卸酸程序,请从列表中将其…

Python工程师面试高频题:return 和 yield之间到底有啥区别?

在编程语言 Python 中&#xff0c;yield 和 return 是两个在函数中用于返回值的关键字&#xff0c;但它们在功能和使用场景上有着本质的区别。理解这两者的区别&#xff0c;对于编写更高效、更灵活的 Python 代码至关重要。 看图说话 首先我们来看下面这张图片&#xff0c;该…

跨平台桌面应用 Electron 入门学习

本文章主要为该视频的学习笔记&#xff0c;如果侵权会速删。 Electron 01 课程介绍_哔哩哔哩_bilibiliElectron 01 课程介绍, 视频播放量 3046、弹幕量 0、点赞数 75、投硬币枚数 43、收藏人数 179、转发人数 2, 视频作者 极客丶张德龙, 作者简介 当你的能力还不足以撑起自己的…

使用UDP实现TCP的功能,会带来什么好处?

比较孤陋寡闻&#xff0c;只知道QUIC TCPQUIC握手延迟TCP需要三次握手TLS握手三次握手TLS握手放在一起&#xff0c;实现0RTT头阻塞问题TCP丢失保文&#xff0c;会影响所有的应用数据包基于UDP封装传输层Stream&#xff0c;Stream内部保序&#xff0c;Stream之间不存在相互影响…

Coursera吴恩达《深度学习》课程总结(全)

这里有Coursera吴恩达《深度学习》课程的完整学习笔记&#xff0c;一共5门课&#xff1a;《神经网络和深度学习》、《改善深层神经网络》、《结构化机器学习项目》、《卷积神经网络》和《序列模型》&#xff0c; 第一门课&#xff1a;神经网络和深度学习基础&#xff0c;介绍一…

每日一题(leetcode238):除自身以外数组的乘积--前缀和

不进阶是创建两个数组&#xff1a; class Solution { public:vector<int> productExceptSelf(vector<int>& nums) {int nnums.size();vector<int> left(n);vector<int> right(n);int mul1;for(int i0;i<n;i){mul*nums[i];left[i]mul;}mul1;for…

攻防世界12-baby_web

12-baby_web 题目说想想初始页面是哪个&#xff0c;一般都是index.php&#xff0c;然后如题分析即可。 我们在链接后面拼接上/index.php&#xff0c;返回后发现界面又回到了1.php&#xff0c;有可能是重定向。 我们点击检查-网络&#xff0c;发现没有index的请求&#xff0c;…

牛客_顺时针打印矩阵_C++题解

题目来源&#xff1a;牛客 题目缩写&#xff1a;给你一个矩阵&#xff08;vector<vector<int>>&#xff09;让你将它的值按顺时针的方式存在一个一维vector<int>中&#xff0c;然后返回&#xff1b; 简要分析&#xff1a; ① 迭代&#xff0c;先打印第一…

数据预处理:删除文件夹(包括子文件夹)里面所有非RGB的图像

在做ai项目的时候&#xff0c;比如图像分类和目标检测&#xff0c;数据里面可能有rgb图和灰度图&#xff0c;但是灰度图的通道数只有1&#xff0c;而rgb图的通道数有3。 因此要进行数据预处理&#xff0c;下面代码就可以删除文件夹&#xff08;包括子文件夹&#xff09;里面所有…

编曲知识18:EQ均衡器 齿音处理 呼吸音处理 口水音处理

EQ均衡器 齿音处理 呼吸音处理 口水音处理小鹅通-专注内容付费的技术服务商https://app8epdhy0u9502.pc.xiaoe-tech.com/live_pc/l_66151c90e4b092c1187ac699?course_id=course_2XLKtQnQx9GrQHac7OPmHD9tqbv 均衡器 均衡器 Equalizer(简称EQ) 人耳接受频率:20hz—20khz …

系统架构最佳实践 -- API网关架构设计

目录 1.什么是API网关&#xff1f; 2.API网关的核心功能 3.架构设计原则 4.API网关的实现方式 5.常见的API网关工具和框架 6.实际案例分析 API网关是现代微服务架构中的重要组件&#xff0c;它充当了前端和后端微服务之间的中介。本文将介绍API网关的架构设计原则和实现方…

AI模型大PK

&#x1f916;AI模型大PK&#xff01;免费测试GPT-4等36款顶级聊天机器人 近年来&#xff0c;大型语言模型&#xff08;LLM&#xff09;的发展日新月异&#xff0c;各大科技巨头和研究机构纷纷推出了自己的聊天机器人。那么&#xff0c;如何才能知道哪个模型更强大、更智能呢&…

Leetcode 剑指 Offer II 073.爱吃香蕉的狒狒

题目难度: 中等 原题链接 今天继续更新 Leetcode 的剑指 Offer&#xff08;专项突击版&#xff09;系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 狒狒喜欢吃香蕉。这里有 N 堆香蕉&#xff0c;第 i 堆中有 piles…

华为海思数字芯片设计笔试第二套

1.声明 下面的题目作答都是自己认为正确的答案&#xff0c;并非官方答案&#xff0c;如果有不同的意见&#xff0c;可以评论区交流。 这些题目也是笔者从各个地方收集的&#xff0c;感觉有些题目答案并不正确&#xff0c;所以在个别题目会给出自己的见解&#xff0c;欢迎大家讨…

【静态分析】静态分析笔记04 - 数据流分析(理论)

参考&#xff1a; 【课程笔记】南大软件分析课程4——数据流分析基础&#xff08;课时5/6&#xff09; - 简书 --------------------------------------------------------------------------- 1. 迭代算法 本质&#xff1a;常见的数据流迭代算法&#xff0c;目的是通过迭代…

安卓ARCore:增强现实技术在Android平台上的实现及其应用

摘要 本文旨在全面剖析安卓ARCore这一Google针对Android设备开发的增强现实&#xff08;AR&#xff09;平台&#xff0c;阐述其工作原理、核心技术、性能优势与局限性以及实际应用场景&#xff0c;并辅以代码示例以增进理解。ARCore通过先进的计算机视觉技术和传感器数据融合&a…

小米暑期实习NLP算法工程师面试题8道|含解析

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学&#xff0c;针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 基于大模…