Leetcode 261. Graph Valid Tree 无向图成环问题

题目大意

Given n nodes labeled from 0 to n-1 and a list of undirected edges (each edge is a pair of nodes), write a function to check whether these edges make up a valid tree.

Example 1:

Input: n = 5, and edges = [[0,1], [0,2], [0,3], [1,4]]
Output: true

Example 2:

Input: n = 5, and edges = [[0,1], [1,2], [2,3], [1,3], [1,4]]
Output: false

是否成环问题

这道题可以联系 Leetcode 207. course schedule 一同分析,当我们把题意扯开,他们的核心都是判断一个图是有环图,还是无环图。
而这两个问题的核心区别在于向的问题,261 Graph Valid Tree 是判断无向图是否有环,而207 course schedule 是判断有向图是否有环。
我把这个类型的规律总结如下,
如果题目给出向前依赖关系,即给定a依赖于b,c,d,e, 则DFS更适合;
如果题目给出向后依赖关系,即给定a支持b,c,d,e,则BFS更适合;
如果题目给出无向图,则BFS与DFS大致等价

BFS 实现

class Solution {
    public boolean validTree(int n, int[][] edges) {
        if (n==0||n==1) return true;
        if (edges==null||edges.length==0) return false;
        List<Integer>[] graph = (ArrayList<Integer>[]) new ArrayList[n];
        for (int[] edge:edges){
            if (graph[edge[0]]==null) graph[edge[0]] = new ArrayList<>();
            if (graph[edge[1]]==null) graph[edge[1]] = new ArrayList<>();
            graph[edge[0]].add(edge[1]);
            graph[edge[1]].add(edge[0]);
        }
        int root = edges[0][0];
        List<Integer> queue = new ArrayList<>();
        HashSet<Integer> visited = new HashSet<>();
        queue.add(root);
        while (!queue.isEmpty()){
            int number = queue.size();
            for (int i=0;i<number;i++){
                int node = queue.remove(0);
                if (visited.contains(node)) return false;
                visited.add(node);
                queue.addAll(graph[node]);
                for (int dest:graph[node]){
                    graph[dest].remove((Integer)node);
                }
            }
        }
        return visited.size()==n;
    }
}

DFS实现

class Solution {

    private HashSet<Integer> visited;
    private int n;
    private int[][] graph;

    private boolean dfs(int node){
        for (int dest=0;dest<n;dest++){
            if (graph[node][dest] == 0) continue;
            if (visited.contains(dest)) return false;
            visited.add(dest);
            graph[node][dest] = 0;
            graph[dest][node] = 0;
            if (!dfs(dest)) return false;
        }
        return true;
    }

    public boolean validTree(int n, int[][] edges) {

        if (n==0||n==1) return true;
        if (edges==null || edges.length==0) return false;
        this.n = n;
        graph = new int[n][n];
        visited = new HashSet<>();
        for (int[] edge:edges){
            graph[edge[0]][edge[1]] = 1;
            graph[edge[1]][edge[0]] = 1;
        }
        visited.add(edges[0][0]);
        int root = edges[0][0];
        return dfs(root) && visited.size()==n;
    }
}


Leave a Reply

Your email address will not be published. Required fields are marked *