常见算法之并查集

今天写了一道力扣题,547. 省份数量,第一眼没看懂,总觉得一个省之间不相连也可以的,看了下例题后立刻想到了考试前学过的并查集,用在这道题上最为合适了。

题目是这样的,给定方阵,若某点值为1,则点下标代表的i,j两城市相连接,如果是相邻的城市为同一个省,具有那种等量替换的性质,(a==b,b==c则a==c的),最终让算几个省份,这不就是把相同省份的城市分为了一个集合中,最后计算有多少个集合的问题了吗。

有一句话说的好,我们由和周围的人和社会关系组成,对于每一个个体,在不产生社会关系前都是独立的个体,所以我们属于自己。这个方法也一样,在没形成关系之前,我们都是属于我们自己的。所以有

        for (int i = 1; i <=(个体数量); i++) {
            father[i]=i;//每一个结点的父节点都是自己
        }

产生联系:

当两个点产生联系时候,就对这两个点合并。

    public static void unoin(int a,int b){
        father[findfather(a)]=findfather(b);
    }

    public static int findfather(int a){
        if(a==father[a]){
            return a;
        }
        father[a]=findfather(father[a]);
        return father[a];
    }

这两个方法的作用就是把两个结点合并起来的关键。

对于每个结点来说,他属于一个集合内,这个集合总有一个父节点,这个父节点是真正的父节点,是这个集合的”创始人“,投靠门派,就找老大,就找这个创始人,所以有了,如果没找到a!=father[a]就一直递归的找,直到找到为止。然后将这个集合的根节点加入新集合,则合并成功。

father[findfather(a)]=findfather(b);

最后对 判断几个老大即可,(剩下的小弟点都归并到老大这里了)。

        int count=0;
        for (int i =1; i <=n*m; i++) {
            if(findfather(i)==i){
                count++;
            }
        }

完整代码:

    public static int findCircleNum(int[][] isConnected) {
        int citynum=isConnected.length;
        int []father=new int[isConnected.length];//记录每一个结点的父节点 最后也只需要 判断有几个父亲 就是几个省份
        for (int i = 0; i < father.length; i++) {
            father[i]=i;
        }
        //遍历相连的结点 归并为一组
        for (int i = 0; i < isConnected.length; i++) {
            for (int j = 0; j < isConnected.length; j++) {
                if(isConnected[i][j]==1){
                    //如果相连 归并
                    hebing(father,i,j);
                }
            }
        }
        int num=0;
        for (int i = 0; i <citynum ; i++) {
            if(find(i,father)==i){
                num++;
            }
        }
        return num;
    }

    public static void hebing(int []father,int i,int j){
        father[find(i,father)]=find(j,father);
    }
    public static int  find(int i,int []father){
        if(father[i]!=i){
            father[i]=find(father[i],father);
        }
        return father[i];
    }

 这样的题有很多种,像以前写的找冰岛数量,判断两个人是不是亲戚之类都是这样思想。

并查集的模板基本上是这样,小的细节需要自己进行判断。

今天郑州的风有点大,早上十点才起床,这几天的气温又下去了,按说往年5.1气温都该热起来了,但今年这时候又穿起来外套了,昨天是微信小程序答辩,感觉没学多少东西关于小程序,这些新技术有时候感觉学了不是很有用,因为这些东西的原理都被封装起来了,底层的逻辑看不到,用久了很难提升,另外感觉小程序这个东西很潦草,这个开发者工具的软件也是。倒不如多学点计算机系统,原理这些。学校栅栏的花开了,昨晚打电话的时候看到的,很漂亮,不艳,不俗。晚香浮处,见蔷薇半吐。花花草草,这些都是生活中的情趣。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值