leetcode刷题学习(10)

阅读更多

前言:考虑到本人是能力有限,算法题解只能示例一种本人能够理解和实现的方式,可能不是最优的。

 

一、朋友圈(题号:547)

    班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友。所谓的朋友圈,是指所有朋友的集合。

    给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。

 

示例 1:

输入: 
[[1,1,0],
 [1,1,0],
 [0,0,1]]
输出: 2 
说明:已知学生0和学生1互为朋友,他们在一个朋友圈。
第2个学生自己在一个朋友圈。所以返回2。
示例 2:

输入: 
[[1,1,0],
 [1,1,1],
 [0,1,1]]
输出: 1
说明:已知学生0和学生1互为朋友,学生1和学生2互为朋友,所以学生0和学生2也是朋友,所以他们三个在一个朋友圈,返回1。

 

    注意:

    1)N 在[1,200]的范围内。

    2)对于所有学生,有M[i][i] = 1。

    3)如果有M[i][j] = 1,则有M[j][i] = 1。

 

    解题思路:典型的并查集算法。

public class TestMain {

    public static void main(String[] args) {
        int[][] s1 = {{1,1,0},{1,1,0},{0,0,1}};
        System.out.println(execute(s1));


        int[][] s2 = {{1,1,0},{1,1,1},{0,1,1}};
        System.out.println(execute(s2));
    }


    public static int execute(int[][] source) {
        if (source == null || source.length == 0) {
            return 0;
        }
        int m = source.length;
        UnionFind unionFind = new UnionFind(m);
        for (int i = 0; i < m; i++) {
            //此前的元素,已在此前
            for (int j = i + 1; j < m; j++) {
                if (source[i][j] == 1) {
                    unionFind.union(i, j);
                }
            }
        }
        return unionFind.count;
    }

    /**
     * 并查集
     * 判断节点联通性
     */
    public static class UnionFind {
        //不同树的个数
        private int count;
        private int[] root;//联通的根节点

        public UnionFind(int m) {
            root = new int[m];//比如三行三列,最多也是3个人,最多也是3个朋友圈
            for (int i = 0; i < m; i++) {
                root[i] = i;//便于构建和查询,起始值为自己的索引值
            }
            count = m;//起始值为,每个人一个朋友圈
        }

        public void union(int i, int j) {
            int x = find(i);//i所属的树或者组
            int y = find(j);
            if (x != y) {
                count--;//如果此前不属于同一个树(组),则建立关系,归为一组;
                root[x] = y;//path compression
            }
        }

        private int find(int i) {
            if (root[i] == i) {
                return i;
            }
            return find(root[i]);//压缩路径,同一组,都指向跟索引节点
        }
    }

}

 

你可能感兴趣的:(leetcode刷题学习(10))