leetcode_547_朋友圈_并查集解法

  1 package cn.leetcode.circleoffriends_547;
  2 
  3 import java.util.HashSet;
  4 
  5 /**
  6  * 班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友。所谓的朋友圈,是指所有朋友的集合。
  7  * 给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。
  8  *
  9  * 示例 1:
 10  * 输入:
 11  * [[1,1,0],
 12  * [1,1,0],
 13  * [0,0,1]]
 14  * 输出:2
 15  * 解释:已知学生 0 和学生 1 互为朋友,他们在一个朋友圈。
 16  * 第2个学生自己在一个朋友圈。所以返回 2 。
 17  *
 18  * 示例 2:
 19  * 输入:
 20  * [[1,1,0],
 21  * [1,1,1],
 22  * [0,1,1]]
 23  * 输出:1
 24  * 解释:已知学生 0 和学生 1 互为朋友,学生 1 和学生 2 互为朋友,所以学生 0 和学生 2 也是朋友,所以他们三个在一个朋友圈,返回 1 。
 25  *
 26  * 提示:
 27  * 1 <= N <= 200
 28  * M[i][i] == 1
 29  * M[i][j] == M[j][i]
 30  *
 31  * 参考资料:https://www.cnblogs.com/noKing/p/8018609.html
 32  */
 33 public class Solution {
 34 
 35     public static void main(String[] args) {
 36 //        int[][] arr = new int[][]{{1, 1, 0}, {1, 1, 0}, {0, 0, 1}};
 37         int[][] arr = new int[][]{{1, 0, 0, 1}, {0, 1, 1, 0}, {0, 1, 1, 1}, {1, 0, 1, 1}};
 38         Solution s = new Solution();
 39 
 40         System.out.println(s.findCircleNum(arr));
 41     }
 42 
 43     /**
 44      * 一共又多少个朋友圈
 45      * @param M
 46      * @return
 47      */
 48     public int findCircleNum(int[][] M) {
 49         UnionFind union = new UnionFind(M.length);
 50         int ret = union.findCircleNum(M);
 51 //        union.printArr();
 52         return ret;
 53     }
 54 
 55 
 56 }
 57 
 58 /**
 59  *并查集具体实现
 60  */
 61 class UnionFind {
 62     private static int[] leader;
 63     private static int[] weight;
 64     private static int size;
 65 
 66     /**
 67      * 一共有多少个组
 68      * @param M
 69      * @return
 70      */
 71     public static int findCircleNum(int[][] M) {
 72         for (int i = 0; i < M.length; i++) {
 73             for (int j = 0; j < M[i].length; j++) {
 74                 if (M[i][j] != 0 && i != j) {
 75                     unionElements(i, j);
 76                 }
 77             }
 78         }
 79         //用HashSet不重复性记录有多少个不同的组
 80         int leaderVal=0;
 81         HashSet<Integer> set = new HashSet();
 82         for (int i = 0; i < leader.length; i++) {
 83             leaderVal=find(leader[i]);
 84             set.add(leaderVal);
 85         }
 86         return set.size();
 87     }
 88 
 89     /**
 90      * 构造函数
 91      * @param size
 92      */
 93     public UnionFind(int size) {
 94         this.leader = new int[size];
 95         this.weight = new int[size];
 96         this.size = size;
 97         for (int i = 0; i < size; i++) {
 98             this.leader[i] = i;
 99             this.weight[i] = 1;
100         }
101     }
102 
103     /**
104      * 查询最终teamLeader的值
105      * @param element
106      * @return
107      */
108     public static int find(int element) {
109         while (element != leader[element]) {
110             leader[element] = leader[leader[element]]; // 路径压缩 (非最终leader结点)
111             element = leader[element];
112         }
113         return element;
114     }
115 
116     public static boolean isConnected(int firstElement, int secondElement) {
117         return find(firstElement) == find(secondElement);
118     }
119 
120     public static void unionElements(int firstElement, int secondElement) {
121         int firstRoot = find(firstElement);
122         int secondRoot = find(secondElement);
123 
124         //如果已经属于同一个集合了,就不用再合并了。
125         if (firstRoot == secondRoot) {
126             return;
127         }
128         //谁小弟多谁说了算
129         if (weight[firstRoot] > weight[secondRoot]) {
130             leader[secondRoot] = firstRoot;
131             weight[firstRoot] += weight[secondRoot];
132         } else {
133             leader[firstRoot] = secondRoot;
134             weight[secondRoot] += weight[firstRoot];
135         }
136     }
137 
138     public static void printArr() {
139         for (int p : leader) {
140             System.out.print(p + "\t");
141         }
142         System.out.println();
143     }
144 
145 }

 

posted @ 2014-06-25 00:11  卖油翁的牛  阅读(874)  评论(0编辑  收藏  举报