【每日一题Day61】寻找图中是否存在路径 | BFS 并查集

12 篇文章 0 订阅
5 篇文章 0 订阅

寻找图中是否存在路径【LC1971】

There is a bi-directional graph with n vertices, where each vertex is labeled from 0 to n - 1 (inclusive). The edges in the graph are represented as a 2D integer array edges, where each edges[i] = [ui, vi] denotes a bi-directional edge between vertex ui and vertex vi. Every vertex pair is connected by at most one edge, and no vertex has an edge to itself.

You want to determine if there is a valid path that exists from vertex source to vertex destination.

Given edges and the integers n, source, and destination, return true if there is a valid path from source to destination, or false otherwise*.*

2022/12/19
开始补昨天的

  • 思路:使用BFS寻找是否存在目的地到终点的有效路径,从source开始按照层次依次遍历每一层的顶点,判断是否可以达到destination

  • 实现:

    • 首先构建邻接表adList,然后使用队列存储最近访问过的顶点,并使用boolean数组isUsed记录每个顶点的访问状态。
    • 初始时将source设为已访问,并且将其加入队列。之后每次将队列中的节点出队,并将其能够到达的未访问过的节点入队。如果访问到destination,则直接返回true;如果队列为空,仍未访问到destination,则返回false
    class Solution {
        public boolean validPath(int n, int[][] edges, int source, int destination) {
            boolean[] isUsed = new boolean[n];
            List<Integer>[] adList = new List[n];
            Deque<Integer> deque = new LinkedList<>();
            // 初始化邻接表
            for (int i = 0; i < n; i++){
                adList[i] = new ArrayList<Integer>();
            }
            for (int[] edge : edges){
                int u = edge[0], v = edge[1];
                adList[u].add(v);
                adList[v].add(u);
            }
            // 添加起点
            deque.add(source);
            isUsed[source] = true;
            // BFS搜索
            while (!deque.isEmpty()){
                int u = deque.pollFirst();
                if (u == destination){
                    return true;
                }
                for (Integer next : adList[u]){    
                    if (!isUsed[next]){
                        deque.addLast(next);
                        isUsed[next] = true;
                    }
                }
            }
            return false;
        }
    }
    
    • 复杂度分析
      • 时间复杂度: O ( n + m ) O(n+m) O(n+m) n n n为图中顶点的数目, m m m为图中边的数目。对于图中的每个顶点或者每条边,我们最多只需访问一次,因此时间复杂度为 O ( n + m ) O(n+m) O(n+m)
      • 空间复杂度: O ( n + m ) O(n+m) O(n+m),空间复杂度主要取决于邻接表、记录每个顶点访问状态的数组和队列,邻接顶点列表需要的空间为 O ( n + m ) O(n+m) O(n+m),记录访问状态需要 O ( n ) O(n) O(n)的空间,进行广度优先搜索时队列中最多只有 n n n个元素,因此总的空间复杂度为 O ( n + m ) O(n+m) O(n+m)
并查集
  • 思路:使用并查集判断两个节点的连通性,如果在并查集中sourcedestination的根相同,那么证明两个点连通,否则不连通

  • 实现

    • 首先初始化并查集,每个节点的根节点均为自身
    • 然后构建并查集,使用join将每条边的两个节点合并
    • 最后判断sourcedestination的根是否相同,若相同则返回true
    class Solution {
        private int[] father;
        public boolean validPath(int n, int[][] edges, int source, int destination) {
            // 初始化并查集
            father = new int[n];
            for (int i = 0; i < n; i++){
                father[i] = i;
            }
            // 构建并查集
            for (int[] edge : edges){
                join(edge[0],edge[1]);
            }
            // 判断根是否相同
            return isSame(source, destination);
        }
        private int find(int u){
            if (father[u] != u){
                father[u] = find(father[u]);
            }
            return father[u];
        }
        private void join (int u, int v){
            u = find(u);
            v = find(v);
            if (u == v) return;
            father[v] = u;
        }
        private Boolean isSame (int u, int v){
            u = find(u);
            v = find(v);
            return u == v;
        }
    }
    
    • 复杂度分析
      • 时间复杂度: O ( n + α ( m ) ∗ m ) O(n+\alpha (m)*m) O(n+α(m)m) n n n为图中顶点的数目, m m m为图中边的数目。其中 α \alpha α为阿克曼函数的反函数,其增长极其缓慢,也就是说其单次操作的平均运行时间可以认为是一个很小的常数。
      • 空间复杂度: O ( n ) O(n) O(n),空间复杂度主要取决于并查集,并查集需要 O ( n ) O(n) O(n)的空间,因此总的空间复杂度为 O ( n ) O(n) O(n)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值