Java常见算法(六)【省份数量- 分组算法:深度优先、广度优先、并查集 】

省份数量-经典的分组算法

https://www.bilibili.com/video/BV1Jv411A7Ty?p=34
在这里插入图片描述
比如现在有三个城市:A城市、B城市、C城市,其中 A 城市与 B城市相连,C城市与A、B城市都不相连。
画图展示:
在这里插入图片描述
然后我们得到的数组是这样的:
例如:A城市与自己相连,A城市与B城市相连,A城市与C不相连,所以得到:{1,1,0 } 。后面两个城市的关系也是类似,不再描述…

所以最终用数组表示三个城市的关系是这样的:

{
    
     {
    
    1,1,0 } , {
    
     1,1,0 } , {
    
     0, 0, 1} }

这里说明一下我们的入参和出参,入参是一个城市关系的数组,出参是省份数量。 省份数量是这样认定的,比如我们上面提到的A、B、C 城市关系,出参就是 2 ,我们认为只要是关联的的城市,就在同一个省份。

所以:

{
    
    1,0,0 } , {
    
     0,1,0 } , {
    
     0, 0, 1}

此数组的城市关系出参为 3,也就是说有三个省份。

1、深度优先遍历

https://www.bilibili.com/video/BV1Jv411A7Ty?p=35

 //1、深度优先遍历
    public static int getProvince(int[][] citysConnected){
    
    
        int citys=citysConnected.length;
        boolean[] visited = new boolean[citys];
        int provinces=0;//计数器
        for (int i = 0; i < citys; i++) {
    
    
            if(!visited[i]){
    
    
                //递归,深度优先
                dfs(i,citys,visited,citysConnected);
                provinces++;
            }
        }
        return provinces;
    }

    private static void dfs(int i, int citys, boolean[] visited, int[][] citysConnected) {
    
    
        for (int j = 0; j < citys; j++) {
    
    
            if(citysConnected[i][j]==1 && !visited[j]){
    
    
                visited[j]=true;
                dfs(j,citys,visited,citysConnected);
            }
        }
    }

2、广度优先

https://www.bilibili.com/video/BV1Jv411A7Ty?p=36

 //2、广度优先
    public static int getProvince1(int[][] citysConnected){
    
    
        int citys=citysConnected.length;
        boolean[] visited = new boolean[citys];
        int provinces=0;//计数器
        Queue<Integer> queue=new LinkedList<Integer>();
        for (int i = 0; i < citys; i++) {
    
    
            if(!visited[i]){
    
    
                queue.offer(i);
                while (!queue.isEmpty()){
    
    
                    int k=queue.poll();
                    visited[k]=true;
                    for (int j = 0; j <citys ; j++) {
    
    
                        if(citysConnected[i][j]==1 && !visited[j]){
    
    
                            queue.offer(j);
                        }
                    }
                }
                provinces++;
            }
        }
        return provinces;
    }

3、并查集 算法

https://www.bilibili.com/video/BV1Jv411A7Ty?p=37

 //3、并查集
    private static int mergeFind(int[][] citysConnected){
    
    
        int citys = citysConnected.length;
        int[] head=new int[citys];
        int[] level=new int[citys];
        for (int i = 0; i <citys ; i++) {
    
    
            head[i]=i;
            level[i]=1;
        }
        for (int i = 0; i <citys ; i++) {
    
    
            for (int j = i+1; j <citys ; j++) {
    
    
                if(citysConnected[i][j]==1){
    
    
                    merge(i,j,head,level);
                }
            }
        }
        int count=0;
        for (int i = 0; i <citys ; i++) {
    
    
            if(head[i]==i){
    
    
                count++;
            }
        }
        return count;
    }

    //合并
    private static void merge(int x, int y, int[] head, int[] level){
    
    
        int i=find(x,head);
        int j=find(y,head);
        //如果根节点一样
        if(i==j){
    
    
            return;
        }
        if(level[i] <= level[j]){
    
    
            head[i]=j;
        }else {
    
    
            head[j]=i;
        }
        if(level[i]==level[j]){
    
    
            level[i]++;
            level[j]++;
        }
    }

    //查找
    private static int find(int x,int[] head){
    
    
        if(head[x]==x){
    
    
            return x;
        }
        head[x]=find(head[x],head);
        return head[x];
    }

实验源码

package com.example.rabbitmq;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.LinkedList;
import java.util.Queue;

@SpringBootTest
/*
    省份数量

 */
class SuanfaApplicationTests20 {
    
    

    //1、深度优先遍历
    public static int getProvince(int[][] citysConnected){
    
    
        int citys=citysConnected.length;
        boolean[] visited = new boolean[citys];
        int provinces=0;//计数器
        for (int i = 0; i < citys; i++) {
    
    
            if(!visited[i]){
    
    
                //递归,深度优先
                dfs(i,citys,visited,citysConnected);
                provinces++;
            }
        }
        return provinces;
    }

    private static void dfs(int i, int citys, boolean[] visited, int[][] citysConnected) {
    
    
        for (int j = 0; j < citys; j++) {
    
    
            if(citysConnected[i][j]==1 && !visited[j]){
    
    
                visited[j]=true;
                dfs(j,citys,visited,citysConnected);
            }
        }
    }

    //2、广度优先
    public static int getProvince1(int[][] citysConnected){
    
    
        int citys=citysConnected.length;
        boolean[] visited = new boolean[citys];
        int provinces=0;//计数器
        Queue<Integer> queue=new LinkedList<Integer>();
        for (int i = 0; i < citys; i++) {
    
    
            if(!visited[i]){
    
    
                queue.offer(i);
                while (!queue.isEmpty()){
    
    
                    int k=queue.poll();
                    visited[k]=true;
                    for (int j = 0; j <citys ; j++) {
    
    
                        if(citysConnected[i][j]==1 && !visited[j]){
    
    
                            queue.offer(j);
                        }
                    }
                }
                provinces++;
            }
        }
        return provinces;
    }

    //3、并查集
    private static int mergeFind(int[][] citysConnected){
    
    
        int citys = citysConnected.length;
        int[] head=new int[citys];
        int[] level=new int[citys];
        for (int i = 0; i <citys ; i++) {
    
    
            head[i]=i;
            level[i]=1;
        }
        for (int i = 0; i <citys ; i++) {
    
    
            for (int j = i+1; j <citys ; j++) {
    
    
                if(citysConnected[i][j]==1){
    
    
                    merge(i,j,head,level);
                }
            }
        }
        int count=0;
        for (int i = 0; i <citys ; i++) {
    
    
            if(head[i]==i){
    
    
                count++;
            }
        }
        return count;
    }

    //合并
    private static void merge(int x, int y, int[] head, int[] level){
    
    
        int i=find(x,head);
        int j=find(y,head);
        //如果根节点一样
        if(i==j){
    
    
            return;
        }
        if(level[i] <= level[j]){
    
    
            head[i]=j;
        }else {
    
    
            head[j]=i;
        }
        if(level[i]==level[j]){
    
    
            level[i]++;
            level[j]++;
        }
    }

    //查找
    private static int find(int x,int[] head){
    
    
        if(head[x]==x){
    
    
            return x;
        }
        head[x]=find(head[x],head);
        return head[x];
    }

    @Test
    public void sf0(){
    
    
        //城市关系 1
        int[][] city1=new int[][]{
    
     {
    
    1,1,0 } , {
    
     1,1,0 } , {
    
     0, 0, 1} };
        //城市关系 2
        int[][] city2=new int[][]{
    
     {
    
    1,0,0 } , {
    
     0,1,0 } , {
    
     0, 0, 1} };
        System.out.println("--------深度优先--------");
        System.out.println(getProvince(city1));
        System.out.println(getProvince(city2));

        System.out.println("--------广度优先--------");
        System.out.println(getProvince1(city1));
        System.out.println(getProvince1(city2));

        System.out.println("--------并查集--------");
        System.out.println(mergeFind(city1));
        System.out.println(mergeFind(city2));


    }

}

结果:

--------深度优先--------
2
3
--------广度优先--------
2
3
--------并查集--------
2
3


猜你喜欢

转载自blog.csdn.net/YL3126/article/details/121551724
今日推荐