国家电网Java面试被问:最小生成树的Kruskal和Prim算法

一、基础概念

1.1 最小生成树定义

最小生成树(Minimum Spanning Tree, MST):在带权连通无向图中,找到一个边的子集,使得:

  1. 包含所有顶点

  2. 没有环

  3. 边的总权重最小

1.2 应用场景

  • 网络设计:以最小成本连接所有城市

  • 电路设计:以最短线路连接所有元件

  • 聚类分析:数据点之间的最小连接

  • 图像分割:像素点之间的最小分割

二、Kruskal算法

2.1 核心思想

贪心策略:每次选择权重最小且不会形成环的边

2.2 算法步骤

text

复制

下载

1. 将图中所有边按权重从小到大排序 2. 初始化一个空集合用于存放MST的边 3. 初始化并查集,每个顶点自成独立集合 4. 按权重从小到大遍历每条边(u, v): a. 如果u和v不在同一个集合(即不连通) b. 将边(u, v)加入MST c. 合并u和v所在的集合 5. 当MST包含n-1条边时结束

篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafc

需要全套面试笔记及答案
【点击此处即可/免费获取】​​​

2.3 代码实现

java

复制

下载

import java.util.*; public class KruskalMST { static class Edge implements Comparable<Edge> { int src, dest, weight; public Edge(int src, int dest, int weight) { this.src = src; this.dest = dest; this.weight = weight; } @Override public int compareTo(Edge other) { return this.weight - other.weight; } } static class UnionFind { int[] parent; int[] rank; public UnionFind(int n) { parent = new int[n]; rank = new int[n]; for (int i = 0; i < n; i++) { parent[i] = i; } } public int find(int x) { // 路径压缩 if (parent[x] != x) { parent[x] = find(parent[x]); } return parent[x]; } public boolean union(int x, int y) { int rootX = find(x); int rootY = find(y); if (rootX == rootY) { return false; // 已在同一集合 } // 按秩合并 if (rank[rootX] > rank[rootY]) { parent[rootY] = rootX; } else if (rank[rootX] < rank[rootY]) { parent[rootX] = rootY; } else { parent[rootY] = rootX; rank[rootX]++; } return true; } } public static List<Edge> kruskalMST(int vertices, List<Edge> edges) { // 1. 按权重排序边 Collections.sort(edges); // 2. 初始化 List<Edge> mst = new ArrayList<>(); UnionFind uf = new UnionFind(vertices); // 3. 处理每条边 for (Edge edge : edges) { if (mst.size() == vertices - 1) { break; // MST已构建完成 } // 4. 检查是否形成环 if (uf.union(edge.src, edge.dest)) { mst.add(edge); } } return mst; } public static void main(String[] args) { int vertices = 4; List<Edge> edges = Arrays.asList( new Edge(0, 1, 10), new Edge(0, 2, 6), new Edge(0, 3, 5), new Edge(1, 3, 15), new Edge(2, 3, 4) ); List<Edge> mst = kruskalMST(vertices, edges); System.out.println("Kruskal MST edges:"); int totalWeight = 0; for (Edge edge : mst) { System.out.println(edge.src + " - " + edge.dest + " : " + edge.weight); totalWeight += edge.weight; } System.out.println("Total weight: " + totalWeight); } }

2.4 时间复杂度分析

text

复制

下载

排序边:O(E log E) 或 O(E log V)(因为E ≤ V²) 并查集操作:每个union/find近似O(α(V)),其中α是反阿克曼函数 总复杂度:O(E log E) 或 O(E log V) 空间复杂度:O(V + E)

2.5 适用场景

  • 边数相对较少的稀疏图

  • 边权重需要频繁更新

  • 分布式计算环境

三、Prim算法

3.1 核心思想

顶点扩展策略:从一个顶点开始,逐步扩展生成树

3.2 算法步骤

text

复制

下载

1. 从任意顶点开始,加入MST集合 2. 初始化优先队列(最小堆),存放从MST到非MST顶点的所有边 3. 当MST包含所有顶点时结束: a. 从优先队列取出权重最小的边(u, v) b. 如果v不在MST中: - 将边(u, v)加入MST - 将v加入MST集合 - 将与v相连且另一端不在MST的边加入优先队列

3.3 代码实现

java

复制

下载

import java.util.*; public class PrimMST { static class Edge { int dest, weight; public Edge(int dest, int weight) { this.dest = dest; this.weight = weight; } } static class Pair implements Comparable<Pair> { int vertex; int weight; int parent; // 记录来源顶点 public Pair(int vertex, int weight, int parent) { this.vertex = vertex; this.weight = weight; this.parent = parent; } @Override public int compareTo(Pair other) { return this.weight - other.weight; } } public static List<int[]> primMST(int vertices, List<List<Edge>> graph) { // 1. 初始化 boolean[] inMST = new boolean[vertices]; PriorityQueue<Pair> minHeap = new PriorityQueue<>(); List<int[]> mstEdges = new ArrayList<>(); // 2. 从顶点0开始 minHeap.offer(new Pair(0, 0, -1)); int edgesAdded = 0; int totalWeight = 0; while (!minHeap.isEmpty() && edgesAdded < vertices) { // 3. 取出最小权重的边 Pair current = minHeap.poll(); int u = current.vertex; // 4. 如果顶点已在MST中,跳过 if (inMST[u]) { continue; } // 5. 加入MST inMST[u] = true; totalWeight += current.weight; if (current.parent != -1) { mstEdges.add(new int[]{current.parent, u, current.weight}); edgesAdded++; } // 6. 将相邻边加入优先队列 for (Edge edge : graph.get(u)) { int v = edge.dest; int weight = edge.weight; if (!inMST[v]) { minHeap.offer(new Pair(v, weight, u)); } } } System.out.println("Prim MST total weight: " + totalWeight); return mstEdges; } // 邻接表表示法 public static List<List<Edge>> createGraph(int vertices, int[][] edges) { List<List<Edge>> graph = new ArrayList<>(); for (int i = 0; i < vertices; i++) { graph.add(new ArrayList<>()); } for (int[] edge : edges) { int u = edge[0], v = edge[1], w = edge[2]; graph.get(u).add(new Edge(v, w)); graph.get(v).add(new Edge(u, w)); // 无向图 } return graph; } public static void main(String[] args) { int vertices = 5; int[][] edges = { {0, 1, 2}, {0, 3, 6}, {1, 2, 3}, {1, 3, 8}, {1, 4, 5}, {2, 4, 7}, {3, 4, 9} }; List<List<Edge>> graph = createGraph(vertices, edges); List<int[]> mst = primMST(vertices, graph); System.out.println("Prim MST edges:"); for (int[] edge : mst) { System.out.println(edge[0] + " - " + edge[1] + " : " + edge[2]); } } }

3.4 优化版本:使用优先队列和key数组

java

复制

下载

public class PrimOptimized { public static int primMST(int vertices, int[][] graph) { // key数组:存储到达每个顶点的最小权重 int[] key = new int[vertices]; // parent数组:存储MST中每个顶点的父节点 int[] parent = new int[vertices]; boolean[] inMST = new boolean[vertices]; // 初始化 Arrays.fill(key, Integer.MAX_VALUE); Arrays.fill(parent, -1); key[0] = 0; PriorityQueue<int[]> minHeap = new PriorityQueue<>( (a, b) -> a[1] - b[1] ); minHeap.offer(new int[]{0, key[0]}); while (!minHeap.isEmpty()) { int[] current = minHeap.poll(); int u = current[0]; if (inMST[u]) continue; inMST[u] = true; // 遍历所有相邻顶点 for (int v = 0; v < vertices; v++) { if (graph[u][v] != 0 && !inMST[v] && graph[u][v] < key[v]) { key[v] = graph[u][v]; parent[v] = u; minHeap.offer(new int[]{v, key[v]}); } } } // 计算总权重 int totalWeight = 0; for (int i = 1; i < vertices; i++) { totalWeight += graph[i][parent[i]]; } return totalWeight; } }

3.5 时间复杂度分析

text

复制

下载

使用二叉堆:O((V + E) log V) ≈ O(E log V) 使用斐波那契堆:O(E + V log V) 空间复杂度:O(V + E)

3.6 适用场景

  • 稠密图(边数接近V²)

  • 需要频繁查询MST

  • 图结构动态变化

四、算法对比分析

4.1 对比表格

维度Kruskal算法Prim算法
核心思想按边贪心,避免环按顶点扩展,连接最近顶点
数据结构并查集 + 边排序优先队列 + 访问标记
时间复杂度O(E log E)O(E log V)
空间复杂度O(V + E)O(V + E)
适合图类型稀疏图(E ≈ V)稠密图(E ≈ V²)
实现难度中等(需实现并查集)简单
内存访问随机访问(边数组)局部性较好
并行潜力高(边可并行排序)低(需顺序处理)

4.2 选择建议

text

复制

下载

if (图是稠密的 && 使用邻接矩阵) { 选择Prim算法 } else if (图是稀疏的 && 边已排序) { 选择Kruskal算法 } else if (需要频繁更新边权重) { 选择Kruskal算法 } else if (需要频繁查询MST) { 选择Prim算法 }

五、实际应用示例

5.1 网络布线问题

java

复制

下载

public class NetworkCabling { // 城市连接问题 public static int minimumCableLength(int n, int[][] connections) { // Kruskal实现 List<Edge> edges = new ArrayList<>(); for (int[] conn : connections) { edges.add(new Edge(conn[0], conn[1], conn[2])); } List<Edge> mst = KruskalMST.kruskalMST(n, edges); return mst.stream().mapToInt(e -> e.weight).sum(); } // 检查网络连通性 public static boolean isNetworkConnected(int n, int[][] connections) { UnionFind uf = new UnionFind(n); for (int[] conn : connections) { uf.union(conn[0], conn[1]); } int root = uf.find(0); for (int i = 1; i < n; i++) { if (uf.find(i) != root) { return false; } } return true; } }

5.2 图像分割应用

java

复制

下载

public class ImageSegmentation { // 像素网格生成最小生成树 public static List<Edge> segmentImage(int width, int height, int[][] pixelWeights) { int vertices = width * height; List<Edge> edges = new ArrayList<>(); // 构建4-connected网格图 for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int current = i * width + j; // 向右连接 if (j < width - 1) { int right = i * width + (j + 1); int weight = Math.abs(pixelWeights[i][j] - pixelWeights[i][j + 1]); edges.add(new Edge(current, right, weight)); } // 向下连接 if (i < height - 1) { int down = (i + 1) * width + j; int weight = Math.abs(pixelWeights[i][j] - pixelWeights[i + 1][j]); edges.add(new Edge(current, down, weight)); } } } return KruskalMST.kruskalMST(vertices, edges); } }

篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafc

需要全套面试笔记及答案
【点击此处即可/免费获取】​​​

六、算法变种与优化

6.1 适用于不同场景的变种

java

复制

下载

// 1. 最大生成树(只需修改排序或比较规则) class MaxSpanningTree { public static List<Edge> kruskalMaxST(List<Edge> edges, int vertices) { // 按权重降序排序 Collections.sort(edges, (a, b) -> b.weight - a.weight); // 其余与Kruskal相同 } } // 2. 第K小生成树 class KthMinimumSpanningTree { // 基于MST的边交换策略 } // 3. 度限制生成树 class DegreeConstrainedMST { // 每个顶点有最大连接数限制 }

6.2 性能优化技巧

java

复制

下载

// 1. 边排序优化 // 对于整数权重,可以使用计数排序 O(E + W) public static void countingSortEdges(Edge[] edges, int maxWeight) { // 实现计数排序 } // 2. 内存优化:使用基本类型数组 class PrimMemoryOptimized { // 使用int[][]代替对象,减少内存开销 } // 3. 增量更新:当图动态变化时 class DynamicMST { // 当增加或删除边时,增量更新MST }

七、面试常见问题

7.1 理论问题

  1. 证明Kruskal和Prim算法的正确性

  2. 两个算法的时间复杂度推导过程

  3. 为什么MST的边数总是V-1?

  4. 如何处理带负权重的图?

  5. 如果图不连通,如何找到最小生成森林?

7.2 编程问题

  1. 实现支持删除边的动态MST

  2. 找到所有可能的MST(如果存在权重相同的边)

  3. 在有向图中找到最小树形图

  4. 在流网络中应用MST算法

  5. 并行化Kruskal算法

八、总结要点

8.1 核心记忆点

  1. Kruskal:边排序 + 并查集,适合稀疏图

  2. Prim:顶点扩展 + 优先队列,适合稠密图

  3. 两者都是贪心算法,都能得到全局最优解

  4. MST边数 = 顶点数 - 1

  5. 时间复杂度都是O(E log V)级别

8.2 应用建议

  • 小规模图:两种都可以,Prim实现更简单

  • 大规模稀疏图:优先考虑Kruskal

  • 需要频繁更新:Kruskal更容易维护

  • 实时计算:Prim可以逐步输出结果

通过理解这两种算法的原理、实现和适用场景,可以灵活解决各种最小生成树相关问题。

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

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

相关文章

CRNN OCR与LangChain集成:快速构建文档智能处理流水线

CRNN OCR与LangChain集成&#xff1a;快速构建文档智能处理流水线 &#x1f4d6; 项目简介 在数字化转型加速的今天&#xff0c;文档智能处理已成为企业自动化流程中的关键环节。从发票识别、合同解析到证件信息提取&#xff0c;OCR&#xff08;光学字符识别&#xff09;技术…

Llama Factory性能优化:让你的微调速度提升300%的秘籍

Llama Factory性能优化&#xff1a;让你的微调速度提升300%的秘籍 作为一名长期与大型语言模型打交道的工程师&#xff0c;我深刻理解模型微调过程中的痛点——尤其是当看到训练进度条像蜗牛一样缓慢移动时。最近通过系统实践Llama Factory的各项优化技巧&#xff0c;成功将单次…

24小时开发实战:快速构建图片解密APP原型

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 使用快马平台快速开发一个图片解密APP原型&#xff0c;要求&#xff1a;1. 响应式网页界面&#xff1b;2. 图片上传和预览功能&#xff1b;3. 集成开源的steg库进行解密&#xff1…

企业级系统SSL证书路径问题实战解决方案

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个企业SSL证书管理模拟器&#xff0c;模拟以下场景&#xff1a;1) 多层级CA证书链 2) 混合环境(Java/.NET) 3) 证书自动更新机制。要求&#xff1a;使用DeepSeek模型生成诊断…

基于python的家庭成员亲子相册图片照片管理系统的设计与实现_192n2568

目录系统设计目标技术架构核心功能模块创新点应用价值关于博主开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;系统设计目标 该系统旨在通过Python技术构建一个高效、易用的家庭成员亲子相册…

Kimi类应用核心技术复现:多情感语音合成完整流程

Kimi类应用核心技术复现&#xff1a;多情感语音合成完整流程 &#x1f4cc; 技术背景与核心价值 随着AI语音助手、虚拟主播、有声阅读等应用场景的爆发式增长&#xff0c;传统“机械朗读”式的语音合成已无法满足用户对自然度和表现力的需求。多情感语音合成&#xff08;Emot…

AI配音成本大缩水:Sambert-Hifigan镜像部署,替代商业TTS方案

AI配音成本大缩水&#xff1a;Sambert-Hifigan镜像部署&#xff0c;替代商业TTS方案 一、中文多情感语音合成的技术演进与成本挑战 在智能客服、有声书生成、短视频配音等应用场景中&#xff0c;高质量的中文多情感语音合成&#xff08;Text-to-Speech, TTS&#xff09; 正变…

中文多情感语音合成新选择:Sambert-HifiGan全面解析

中文多情感语音合成新选择&#xff1a;Sambert-HifiGan全面解析 一、引言&#xff1a;中文多情感语音合成的技术演进与现实需求 随着智能语音助手、有声读物、虚拟主播等应用的普及&#xff0c;传统“机械式”语音合成已无法满足用户对自然度和表现力的需求。尤其在中文场景下…

如何用AI自动解决Python请求重试错误

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个Python脚本&#xff0c;使用requests库实现智能重试机制&#xff0c;当遇到网络请求失败时自动重试。要求&#xff1a;1) 支持自定义重试次数和间隔时间 2) 能识别不同类型…

Sambert-HifiGan在虚拟主播中的应用:打造逼真数字人

Sambert-HifiGan在虚拟主播中的应用&#xff1a;打造逼真数字人 引言&#xff1a;语音合成如何赋能虚拟主播&#xff1f; 随着AIGC技术的快速发展&#xff0c;虚拟主播正从“动起来”迈向“说得好”的新阶段。早期的数字人多依赖预录语音或机械式TTS&#xff08;文本转语音&a…

5分钟用VUE UI组件库打造产品原型

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 使用快马平台&#xff0c;输入以下提示词生成一个快速原型的VUE UI组件库项目&#xff1a;生成一个用于快速原型的VUE UI组件库&#xff0c;支持拖拽式界面设计。包含常见的登录页…

智能家居中PCTOLCD2002的实战开发指南

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个智能温控器的LCD显示项目&#xff0c;使用PCTOLCD2002驱动芯片。需要实现&#xff1a;1) 温度数字显示 2) 湿度百分比显示 3) 模式图标(制冷/制热/自动) 4) 设置菜单界面 …

TCL华星光电对Prima的收购进一步对终端市场的把控

品牌与面板厂深化垂直整合&#xff0c;TCL华星收购案是大趋势缩影集邦咨询&#xff08;TrendForce&#xff09;指出&#xff1a;品牌与面板制造商进军 micro/miniLED 领域&#xff0c;垂直整合趋势深化。中国家电巨头 TCL科技 近日宣布&#xff0c;其子公司 TCL华星&#xff08…

Llama Factory魔法书:从零开始构建智能问答系统

Llama Factory魔法书&#xff1a;从零开始构建智能问答系统 为什么选择 Llama Factory&#xff1f; 如果你正在为初创公司开发行业专用的问答系统&#xff0c;却苦于没有足够的预算雇佣AI专家&#xff0c;那么 Llama Factory 就是你的救星。这个开源框架整合了主流的高效训练微…

比传统方法快10倍:VMware故障智能诊断方案

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个VMware故障诊断效率对比工具&#xff0c;包含&#xff1a;1)传统排查流程模拟器&#xff1b;2)AI诊断流程模拟器&#xff1b;3)效率对比仪表盘。工具应记录两种方法在各环…

Android App集成TTS:通过HTTP请求调用本地镜像服务

Android App集成TTS&#xff1a;通过HTTP请求调用本地镜像服务 &#x1f4cc; 背景与需求&#xff1a;移动端语音合成的轻量化落地方案 在智能硬件、无障碍应用、教育类App等场景中&#xff0c;文本转语音&#xff08;Text-to-Speech, TTS&#xff09; 已成为提升用户体验的关…

基于CRNN OCR的营业执照信息自动录入系统

基于CRNN OCR的营业执照信息自动录入系统 &#x1f4d6; 项目背景与业务痛点 在企业服务、金融风控、工商注册等场景中&#xff0c;营业执照信息录入是高频且繁琐的基础操作。传统方式依赖人工逐字输入&#xff0c;不仅效率低下&#xff08;平均耗时3-5分钟/张&#xff09;&…

大数据爬虫python泰州市招聘房价数据分析可视化LW PPT

目录摘要项目技术支持论文大纲核心代码部分展示可定制开发之亮点部门介绍结论源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作摘要 本次分析聚焦泰州市招聘与房价数据&#xff0c;通过Python爬虫技术采集公开数据&#xff0c;结合大数据分析…

3分钟验证:Ubuntu NVIDIA驱动快速测试环境搭建

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个使用Docker快速搭建Ubuntu NVIDIA驱动测试环境的方案&#xff0c;包含&#xff1a;1.基础Ubuntu镜像 2.NVIDIA容器工具包配置 3.驱动版本切换功能 4.简单CUDA测试程序 5.环…

AI如何帮你自动处理CSV数据?快马平台一键生成代码

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个Python脚本&#xff0c;使用Pandas库处理CSV文件。要求&#xff1a;1. 自动识别CSV文件中的列名和数据类型 2. 处理缺失值&#xff08;用列均值填充数值列&#xff0c;用众…