美文网首页
P37-省份数量-并查集

P37-省份数量-并查集

作者: YonchanLew | 来源:发表于2021-05-26 23:06 被阅读0次
//省份数量
/*
* 有n个城市,其中一些彼此相连,另一些没有相连。如果城市a与城市b直接相连,且城市b与城市c直接相连,
* 那么城市a与城市c间接相连
* 省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。
* 给你一个 n * n 的矩阵 isConnected,其中isConnected[i][j]=1表示第i个城市和第j个城市直接相连,
* 而isConnected[i][j]=0表示二者不直接相连
* 返回矩阵中省份(直接或间接相连的是一个省,没有关联的是另一个省)的数量
* */
public class P37 {
    public static void main(String[] args) {
        System.out.println(getProvince(new int[][]{{1,1,0},{1,1,0},{0,0,1}}));  //2
        System.out.println(getProvince(new int[][]{{1,0,0},{0,1,0},{0,0,1}}));  //3
    }

    //并查集,并是合并两个树,查是查根节点,直到该合并的都合并了,树和树之间再没办法合并,题目就解开了
    //合并的时候,是以树高度大的作为根节点,可以减少维护所有节点指向新节点的次数,并且合并后高度还是不变
    //思路:一个一维数组代表城市,不同下标就是不同城市,数组的值是root节点的下标,最后统计这个数组有多少不同的root,就是多少个省
    //直接统计不太好,还可以是 数组下标 == 数组值,就是一个省

    //并查集
    private static int getProvince(int[][] citiesConnected) {
        int cities = citiesConnected.length;     //初始假设每一个城市都是一个省
        int[] head = new int[cities];
        int[] level = new int[cities];       //维护层高,用来减少维护head数组的。
        // 合并的时候,层高相同时,值都加1
        // 层高不同时,小的变为大的值

        for (int i=0; i<cities; i++){
            head[i] = i;        //初始化
            level[i] = 1;
        }

        for(int i=0; i<cities; i++){
            for(int j=i+1; j<cities; j++){
                if(citiesConnected[i][j] == 1){     //属于同一个省,合并
                    merge(i, j, head, level);
                }
            }
        }

        //统计省份数量
        int provinces = 0;
        for(int i=0; i<cities; i++){
            if(head[i] == i){
                provinces++;
            }
        }

        return provinces;
    }

    //合并方法
    static void merge(int x, int y, int[] head, int[] level){
        int i = find(x, head);        //找x的根节点
        int j = find(y, head);        //找y的根节点

        if(i == j){     //代表同一个树
            return;
        }

        //不是同一个树
        if(level[i] <= level[j]){          //合并,矮的合到高的上
            head[i] = j;        //i的level要++
        }else{
            head[j] = i;        //j的level要++
        }

        if(level[i] == level[j]){
            level[i]++;     //比较准确的是把这个判断放在上面,看是i还是j++,不过其实都++并不影响结果,不影响level[i] <= level[j]判断结果
            level[j]++;
        }
    }

    //找根节点
    //如【0,1,1,2,3】,这样root共有2个,分别是0和1索引,但假如4号索引要找根节点,需要递归,直到找到值等于下标的值
    private static int find(int x, int[] head) {
        if(head[x] == x){
            return x;
        }
        head[x] = find(head[x], head);     //还要维护指针,这样下次就不用再次递归找root(head)了
        //[0,1,1,2,1]
        return head[x];
    }

}

相关文章

  • P37-省份数量-并查集

  • [并查集]并查集应用之省份数量

    前言 经过并查集的升级路线一二三四之后,我们现在得到了一个相对来说比较完美的并查集数据结构,从本篇开始应用这个并查...

  • 【leetcode】省份数量 C++/Go(并查集)

    问题描述 有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市...

  • markdown学习

    #并查集 ##并查集的定义 ##并查集的操作

  • 算法模板(四)并查集

    并查集 路径压缩并查集

  • 并查集入门使用

    本文参考自《算法笔记》并查集篇 并查集的定义 什么是并查集?并查集可以理解为是一种维护数据集合的结构。名字中并查集...

  • 并查集练习

    并查集 参考《算法笔记》 三要素:并,查,集。 并差集与一个算法有关,kruskal算法,就可通过并查集实现。 1...

  • 并查集

    并查集 并查集是什么 并查集是一种用来管理元素分组情况的数据结构,并查集可以高效地进行如下操作: 查询元素a和元素...

  • 数据结构与算法(十二)并查集(Union Find)

    本文主要包括以下内容: 并查集的概念 并查集的操作 并查集的实现和优化Quick FindQuick Union基...

  • 并查集

    并查集是什么 并查集是一种用来管理元素分组情况的数据结构。并查集可以高效地进行如下操作。不过需要注意并查集虽然可以...

网友评论

      本文标题:P37-省份数量-并查集

      本文链接:https://www.haomeiwen.com/subject/wybrjltx.html