题解 | #最小生成树#

最小生成树

https://www.nowcoder.com/practice/735a34ff4672498b95660f43b7fcd628

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 返回最小的花费代价使得这n户人家连接起来
     * @param n int整型 n户人家的村庄
     * @param m int整型 m条路
     * @param cost int整型二维数组 一维3个参数,表示连接1个村庄到另外1个村庄的花费的代价
     * @return int整型
     */

    //并查集的定义
    class UnionFind {

        //定义一个parents数组来追溯是否包含集合内
        private int[] parents;

        //传入点的个数来初始化parents
        public UnionFind(int n) {
            this.parents = new int[n];
            //初始化时每个点按顺序对应自己的下标映射(假设顶点从1开始),每个点对应下标对应parents中自己的下标值
            //也可以说初始化时候每个点顶都属于自己的独立集合不依赖不映射任何一个顶点
            for (int i = 0; i < n; i++) {
                parents[i] = i;
            }
        }

        public int find(int index) {
            //函数传入要查找点下标对应parents中的下标值
            //如果该点下标索引对应的值与自己的下标值不对应,
            // 那就说明这个点已经加入了其他点的集合,
            // 它现在索引对应的值就是它依赖点的下标值
            if (parents[index] != index) {
                //那样的话就递归寻找它最终依赖的那个点的下标并且写入它现在的索引位置
                //递归的出口就是最终大家都依赖的那个点,它对应的下标索引还是自己
                parents[index] = find(parents[index]);
            }
            //把索引到的该点依赖的点的下标返回(自己依赖自己那就原值返回)
            return parents[index];
        }


        public boolean isContain(int beginIndex, int endIndex) {
            //查找现在要加入这条边的起点和终点是否在同一个依赖集合,如果在一起那就会形成环
            return find(beginIndex) == find(endIndex);
        }

        public void union(int beginIndex, int endIndex) {
            if (!isContain(beginIndex, endIndex)) {
                //如果这条边起点和终点不在同一个依赖集合,那就把现在的起点加入终点的依赖集合
                parents[find(beginIndex)] = find(
                                                endIndex);//现在目前这个树中所有的点都
                // 依赖于现在的终点find(endIndex)
            }
        }
    }
//边类定义
    class Edge {
        int src;
        int dest;
        int weight;

        public Edge(int src, int dest, int weight) {
            this.src = src;
            this.dest = dest;
            this.weight = weight;
        }
    }

    public int miniSpanningTree (int n, int m, int[][] cost) {
        // write code here
        List<Edge> edgeList = new ArrayList<>();
        for (int[] edge : cost) {
            edgeList.add(new Edge(edge[0] - 1, edge[1] - 1, edge[2]));
        }

        // 按边的权重从小到大排序
        edgeList.sort(Comparator.comparingInt(e -> e.weight));

        UnionFind uf = new UnionFind(n);
        int mstWeight = 0;

        for (Edge edge : edgeList) {
            if (!uf.isContain(edge.src, edge.dest)) {
                uf.union(edge.src, edge.dest);
                mstWeight += edge.weight;
            }
        }

        return mstWeight;
    }
}

全部评论

相关推荐

04-08 11:04
已编辑
北方民族大学 全栈开发
“无名小卒还是名扬天下?”我知道很多人都不觉得我能走到今天这一步,当然,也包括我自己。在我的人生里,有两部作品刻下了最深的印记:《斗破苍穹》与《龙族》。这两部书总被人拿来对照:一边是萧炎的桀骜轻狂,一边是路明非的怯懦衰颓。有人说,天蚕土豆没见过魂天帝,但江南见过真凯撒。我时常觉得自己就是那个衰小孩路明非,可路明非可以开挂,我不可以;我也无数次幻想过能拥有萧炎那般年少轻狂的人生,可我没有他与生俱来的逆天天赋。我只是个平庸的普通人,一个看过《斗破苍穹》却开不了挂的路明非,只能一步一步往上爬。从我下定决心找实习的那一刻起,我就给自己定下了目标:我一定要为字节跳动卖命.jpg。萧炎有他的三年之约,我有我的两年半之约(其实是一年半)。2024.11.20,科大讯飞的第一封实习offer落进邮箱,我迈出了这场奔赴的第一步。2025.8.18,放弃百度转正的安稳机会,转身走进前路未卜的不确定里。我很感谢我在百度的mentor,是她从茫茫人海选中了我,给了我大厂实习的机会。即便那段时间我状态差、产出不理想,她依旧愿意认可我、希望我留下转正。2025.11.14,我选择走进字节跳动,以实习生的身份重新出发,放下过往,清零重来,只为奔赴心之所向。2026.3.25&nbsp;-&nbsp;3.27,三天速通上海飞书,斩获Special&nbsp;Offer。被告知面试通过的那一刻,我的内心无比平静,就像这个offer本就该属于我。不是侥幸,是应得的。这一路,有人看轻过我的出身,不相信我能走到这里;也有人在我看不见前路的时候,替我举过灯。没有他们的鼓励与支撑,就没有今天站在这里的我。我看到了自强不息的激荡,那是一个双非的伟大乐章!我是雨夜迈巴赫,我要开启属于我的新篇章了。
在看牛客的本杰明很勇...:真心祝贺l总 我永远的偶像 我滴神
春招至今,你收到几个面试...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务