Leetcode 第 345 场周赛 Problem D 统计完全连通分量的数量 题目 给你一个整数 n 。现有一个包含 n 个顶点的 无向 图,顶点按从 0 到 n - 1 编号。给你一个二维整数数组 edges 其中 edges[i] = [ai, bi] 表示顶点 ai 和 bi 之间存在一条 无向 边。 返回图中 完全连通分量 的数量。 如果在子图中任意两个顶点之间都存在路径,并且子图中没有任何一个顶点与子图外部的顶点共享边,则称其为 连通分量 。 如果连通分量中每对节点之间都存在一条边,则称其为 完全连通分量 。 1 <= n <= 50 0 <= edges.length <= n * (n - 1) / 2 edges[i].length == 2 0 <= ai, bi <= n - 1 ai != bi 不存在重复的边 解法 并查集 + 图论:通过并查集找到所有连通分量,然后判断每块连通分量的所有边数是否为 n*(n-1)/2,是则代表完全连通分量,因为:边对应的点不错误、无向、不重复、不自连 n 为节点数,m 为边数,时间复杂度:O(α(n)+m),空间复杂度:O(n+m) 代码
private int countCompleteComponents ( int n, int [ ] [ ] edges) { int [ ] parent = unionFind ( n, edges) ;
int res = determineCompleteComponents ( parent, n, edges) ; return res; } private int [ ] unionFind ( int n, int [ ] [ ] edges) { int edgesLen = edges. length; int [ ] parent = new int [ n] ; for ( int i = 0 ; i < n; i++ ) { parent[ i] = i; } for ( int i = 0 ; i < edgesLen; i++ ) { int pointA = edges[ i] [ 0 ] ; int pointB = edges[ i] [ 1 ] ; union ( pointA, pointB, parent) ; } return parent; } private void union ( int pointA, int pointB, int [ ] parent) { int parentA = find ( pointA, parent) ; int parentB = find ( pointB, parent) ; parent[ parentA] = parent[ parentB] ; } private int find ( int pointA, int [ ] parent) { if ( parent[ pointA] == pointA) { return pointA; } parent[ pointA] = find ( parent[ pointA] , parent) ; return parent[ pointA] ; } private int determineCompleteComponents ( int [ ] parent, int n, int [ ] [ ] edges) { Map < Integer , List < Integer > > completeMap = new HashMap < > ( ( n / 3 ) << 2 ) ; for ( int i = 0 ; i < n; i++ ) { int parentPoint = find ( i, parent) ; List < Integer > completeList = completeMap. getOrDefault ( parentPoint, new ArrayList < > ( n) ) ; completeList. add ( i) ; completeMap. put ( parentPoint, completeList) ; }
Map < Integer , Integer > completeEdgesCountMap = new HashMap < > ( ( completeMap. size ( ) / 3 ) << 2 ) ; int edgesLen = edges. length; for ( int i = 0 ; i < edgesLen; i++ ) { int parentPoint = find ( edges[ i] [ 0 ] , parent) ; completeEdgesCountMap. put ( parentPoint, completeEdgesCountMap. getOrDefault ( parentPoint, 0 ) + 1 ) ; }
int count = 0 ; for ( Map. Entry < Integer , List < Integer > > completeEntry : completeMap. entrySet ( ) ) { int completeEdgesCount = completeEdgesCountMap. getOrDefault ( completeEntry. getKey ( ) , 0 ) ; int completePointCount = completeEntry. getValue ( ) . size ( ) ; if ( completePointCount * ( completePointCount - 1 ) / 2 == completeEdgesCount) { count++ ; } } return count; }