力扣:01. 节点间通路

172 阅读2分钟

「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战

描述

节点间通路。给定有向图,设计一个算法,找出两个节点之间是否存在一条路径。

  • 示例 1:
 输入:n = 3, graph = [[0, 1], [0, 2], [1, 2], [1, 2]], start = 0, target = 2
 输出:true
  • 示例 2:
 输入:n = 5, graph = [[0, 1], [0, 2], [0, 4], [0, 4], [0, 1], [1, 3], [1, 4], [1, 3], [2, 3], [3, 4]], start = 0, target = 4
 输出 true
  • 提示:
  • 节点数量n在[0, 1e5]范围内。
  • 节点编号大于等于 0 小于 n。
  • 图中可能存在自环和平行边。

解析

把二维数组转为List<List> 每个List 记录的是当前节点的下一个节点集合,然后递归 从起始点开始找下一个节点集合是否包含终止节点

class Solution {
    private boolean[] visit;
    public boolean findWhetherExistsPath(int n, int[][] graph, int start, int target) {
        List<Integer>[] arr = helper(graph, n);
        visit = new boolean[n];
        return DFS(arr, start, target);
    }
​
    //使用邻接矩阵表示图
    public List<Integer>[] helper(int[][] graph, int n) {
        List<Integer>[] arr = new LinkedList[n];
        for(int i = 0; i < n; i++)
            arr[i] = new LinkedList<>();
        for(int i = 0; i < graph.length; i++) {
            int from = graph[i][0], to = graph[i][1];
            arr[from].add(to);
        }
        return arr;
    }
​
    public boolean DFS(List<Integer>[] arr, int start, int target) {
        //递归跳出标志
        //成功
        if(start == target)
            return true;
        
        //标记当前位
        visit[start] = true;
        for(int num : arr[start]) {
            //下一个没有遍历过的,并且遍历结果可以得到start == target
            if(!visit[num] && DFS(arr, num, target))
                return true;
        }
        return false;
        
    }
}

运行结果:

执行结果:通过

执行用时:

内存消耗:

  • 解法2,使用邻接表和BFS
class Solution {
    public boolean findWhetherExistsPath(int n, int[][] graph, int start, int target) {
        List<Integer>[] arr = helper(graph, n);
        return BFS(arr, n, start, target);
    }
​
    //使用邻接矩阵表示图
    public List<Integer>[] helper(int[][] graph, int n) {
        List<Integer>[] arr = new LinkedList[n];
        for(int i = 0; i < n; i++)
            arr[i] = new LinkedList<>();
        for(int i = 0; i < graph.length; i++) {
            int from = graph[i][0], to = graph[i][1];
            arr[from].add(to);
        }
        return arr;
    }
​
    public boolean BFS(List<Integer>[] arr, int n, int start, int target) {
        Queue<Integer> queue = new LinkedList<>();
        boolean[] visit = new boolean[n];
        //新加入队列的标记已被访问
        visit[start] = true;
        queue.add(start);
        while(!queue.isEmpty()) {
            int index = queue.poll();
            //没有可以到达的下一个节点
            if(arr[index] == null)
                continue;
            for(int num : arr[index]) {
                //成功退出
                if(num == target)
                    return true;
                //已经入队的数据不再重复处理
                if(visit[num])
                    continue;
                else {
                    //新加入队列的标记已被访问
                    visit[num] = true;
                    queue.add(num);
                }
            }
        }
        return false;
    }
}