算法之不定期更新(三)(2018-04-24)

题目

input:

  • n // 代表无向图的顶点数 // 从1开始
  • m // 无向图的边数
  • arr1 // 各边的情况,形如[[1, 2], [3, 4],...](代表顶点0和顶点2相连,顶点3和顶点4相连)
  • arr2 // 希望求得的连通情况数组,形如[[1, 3], [1, 4], ...] (代表希望知道顶点1,顶点3的连通情况,顶点1和顶点4的连通情况)

output: numarr2中可以连通的数量

示例: 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刚做完探索里的初级,还有好多已经说烂了的题就不分享了。)如果有什么意见或者想法欢迎在评论区和我交流

阅读 734

推荐阅读
zxx的技术专栏
用户专栏

zxx的编程求学路内容包含前端文档阅读,源码阅读,不定期的算法思考分享等

1 人关注
7 篇文章
专栏主页