java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846
并查集
解题思路:时间复杂度O( n ∗ l o g 2 n n*log_2n n ∗ l o g 2 n ),空间复杂度O( n n n )
并查集是图论的经典算法,主要用于处理不相交集合的合并问题,常用于求连通子图,求最小生成树的Kruskal算法和求最近公共祖先(LCA)等等 其代码操作非常简单,初始化init,查询find,合并union 初始化操作:用一个数组parent来存储每个顶点的祖先,初始时将自己设置为自己的祖先 查询操作:找到i的祖先,index是否是祖先的条件为,parent[index] == index.入果不满足,就需要找到index的祖先x,并更新parent[index] = x 合并操作:将两个集合index1和index2合并,直接找到两个集合的祖先x和y,让x指向y 根据题目描述,一棵树中,边的数量比结点数量少1,但是现在加了一条边,让这颗树的边和结点数量一致了 树是连通无环的无向图,但是多了一条边就会出现环。也就是说,这道题的本质上就是让我们求出导致环出现的这条边(导致两个顶点属于同一连通分量的边) 使用并查集,每个集合代表一个连通分量,初始每个结点都属于不同连通分量。遍历每一条边连接的两个顶点 两个顶点属于不同连通分量,说明遍历到当前边之前,两个顶点不连通,因此当前边不会导致环的出现,则合并两个顶点的连通分量 两个顶点属于相同连通分量,说明在遍历到当前边之前,两个顶点已经连通(间接),而这条边又将两个顶点直接连通,从而导致环的出现,则它就是罪魁祸首。
class Solution { public int [ ] findRedundantConnection ( int [ ] [ ] edges) { int n = edges. length; int [ ] parent = new int [ n + 1 ] ; for ( int i = 1 ; i <= n; i++ ) { parent[ i] = i; } for ( int i = 0 ; i < n; i++ ) { int [ ] edge = edges[ i] ; int node1 = edge[ 0 ] , node2 = edge[ 1 ] ; if ( find ( parent, node1) != find ( parent, node2) ) { union ( parent, node1, node2) ; } else { return edge; } } return new int [ 0 ] ; } public void union ( int [ ] parent, int index1, int index2) { parent[ find ( parent, index1) ] = find ( parent, index2) ; } public int find ( int [ ] parent, int index) { if ( parent[ index] != index) { parent[ index] = find ( parent, parent[ index] ) ; } return parent[ index] ; }
}