input:算法
n
// 表明无向图的顶点数 // 从1开始m
// 无向图的边数arr1
// 各边的状况,形如[[1, 2], [3, 4],...]
(表明顶点0和顶点2相连,顶点3和顶点4相连)arr2
// 但愿求得的连通状况数组,形如[[1, 3], [1, 4], ...]
(表明但愿知道顶点1,顶点3的连通状况,顶点1和顶点4的连通状况)output:
num
,arr2
中能够连通的数量数组示例: input:code
n = 3
m = 1
arr1 = [[1, 3]]
arr2 = [[2, 3]]
output:
0
leetcode
下面是我解决这个题的时候的思路input
这个题,刚拿到的时候,我最初的想法是使用无向图的邻接矩阵,而后在检查点的时候经过广度优先遍历查看两个点是否连通。实现这个想法以后就发现,时间复杂度真的过高了。每一次都会产生许多的无用查询。hash
而后我想了另一个思路,既然只查询两个点是否连通,那么咱们维护一个连通集合不就能够了。一开始每个孤立的点都是一个单独的连通集合,形如['1', '2', '3', '4']
,在加上一条边以后,就是该边的两个顶点所在的连通集合合并成同一个连通集合,即加上边[1, 3]
后,连通集合变成['13', '2', '4']
。这样,在查询的时候,去寻找顶点B是否在顶点A所处的连通集合里就能够了。因而我写出了以下的代码。io
function solution(n, m, arr1, arr2) { let hash = new Array(n + 1) // 表明每一个点的所在的连通集合,undefined表明这个点还不与其余点相连,0位无效 let map = {} // 保留每一个联通集合的点集 let index = 1 // 下一个联通集合的编号 for (let i = 0; i < m; i++) { // 依次添加边到连通集合里 let edge = arr1[i] let A = edge[0] // 顶点A let B = edge[1] // 顶点B if (hash[A] === undefined && hash[B] === undefined) { // 这两个都是孤立的点,新建一个连通集合 hash[A] = index hash[B] = index map[index++] = [A, B] } else if (hash[B] === undefined) { // 点A不是孤立的,点B是孤立的,把B加入A的连通集合里 hash[B] = hash[A] map[hash[A]].push(B) } else if (hash[A] === undefined) { // 点B不是孤立的,点A是孤立的,把A加入B的连通集合里 hash[A] = hash[B] map[hash[B]].push(A) } else if (hash[A] !== hash[B]) { // A,B均不是孤立的,把B的连通集合,加入A的连通集合里 B_list = map[hash[B]] // B所在的连通集合的顶点列表 group = hash[A] for (let i = B_list.length - 1; i >= 0; i--) { // 每一个顶点的连通集合修改成A的 hash[B_list[i]] = group } map[group] = map[group].concat(map[hash[B]]) delete map[hash[B]] } } let result = 0 // 连通的数量 for (let i = arr2.length - 1; i >= 0; i--) { let test = arr2[i] let groupA = hash[test[0]] let groupB = hash[test[1]] if (groupA && groupB && groupA === groupB) { result++ } } return result }
也就是,用hash来存放对应的点所在的连通集合,map存放连通集合对应的点。function
本期算法小分享就到这里咯(leetcode刚作完探索里的初级,还有好多已经说烂了的题就不分享了。)若是有什么意见或者想法欢迎在评论区和我交流test