题目
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:
n = 3
m = 1
arr1 = [[1, 3]]
arr2 = [[2, 3]]
output:
0
下面是我解决这个题的时候的思路
解题思路
这个题,刚拿到的时候,我最初的想法是使用无向图的邻接矩阵,然后在检查点的时候通过广度优先遍历查看两个点是否连通。实现这个想法之后就发现,时间复杂度真的太高了。每一次都会产生许多的无用查询。
然后我想了另外一个思路,既然只查询两个点是否连通,那么我们维护一个连通集合不就可以了。一开始每一个孤立的点都是一个单独的连通集合,形如['1', '2', '3', '4']
,在加上一条边之后,就是该边的两个顶点所在的连通集合合并成同一个连通集合,即加上边[1, 3]
后,连通集合变成['13', '2', '4']
。这样,在查询的时候,去寻找顶点B是否在顶点A所处的连通集合里就可以了。于是我写出了如下的代码。
代码
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存放连通集合对应的点。
本期算法小分享就到这里咯(leetcode刚做完探索里的初级,还有好多已经说烂了的题就不分享了。)如果有什么意见或者想法欢迎在评论区和我交流
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。