[LeetCode]Graph Valid Tree

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.node

For example:app

Given n = 5 and edges = [[0, 1], [0, 2], [0, 3], [1, 4]], return true.spa

Given n = 5 and edges = [[0, 1], [1, 2], [2, 3], [1, 3], [1, 4]], return false.code

Note: you can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges.排序

分析

这种验证有效的图都是一类题。无非就是几种方法,好比DFS。注意树有个特征就是一个child不能有两个parent, 根平时拓扑排序找环的的差异,固然因为这道题是无向图,不用考虑这方面。这题有几个要注意的地方,好比一个树只能有一个root,若是这个树存在多个root, 那确定无效。get

因为这道题是无向图,那么咱们其实能够从任意一个点开始DFS,不用必须从root,由于无向图从任意一点均可以遍历到整块部分。添加edge的时候两个方向都添就能够了,另外就是还有个注意的地方就是若是在遍历neighbors的时候,本身parent不要遍历,不然直接返回false觉得有环了。总结一句就是,这种无向图每一个点遍历一次就能够了,不然就意味着有环。it

若是这道题换成是有向图的话,解法见下文。io

复杂度

time: O(V + E), space: O(h)function

代码

public class Solution {
     public boolean validTree(int n, int[][] edges) {
        List<Integer>[] graph = new List[n];

        for (int i = 0; i < n; i++) {
            graph[i] = new ArrayList<Integer>();
        }

        for (int i = 0; i < edges.length; i++) {
            graph[edges[i][0]].add(edges[i][1]);
            graph[edges[i][1]].add(edges[i][0]);
        }

        boolean[] visited = new boolean[n];
        if (!dfs(graph, 0, visited, -1)) {
            return false;
        }
        
        // 检测是否存在多个root, 如是意味着图无效
        for (int i = 0; i < n; i++) {
            if (!visited[i]) {
                return false;
            }
        }

        return true;
    }

    private boolean dfs(List<Integer>[] graph, int i, boolean[] visited, int prev) {
        // 发现环
        if (visited[i]) {
            return false;
        }
        visited[i] = true;

        for (int num : graph[i]) {
            if (prev != num && !dfs(graph, num, visited, i)) {
                return false;
            }
        }

        return true;
    }
}

Graph Valid Tree(Directed Edges)

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

For example:

Given n = 5 and edges = [[0, 1], [0, 2], [0, 3], [1, 4]], return true.

Given n = 5 and edges = [[0, 1], [1, 2], [2, 3], [1, 3], [1, 4]], return false.
Given n = 5 and edges = [[0, 1], [1, 2], [3, 4]], return false.

分析

有向图要注意的地方不只是不能有多个root存在,与上题不一样的是须要从root开始遍历才能慢慢遍历到整个图,其余方面基本跟上题同样,遍历过程当中一个点只能visit一次,不然便是那种一个child多个parent状况。

复杂度

time: O(V+E), space: O(h)

代码

public class Solution {
    public boolean validTree(int n, int[][] edges) {
        List<Integer>[] graph = new List[n];
        Set<Integer> inDegree = new HashSet<>();

        for (int i = 0; i < n; i++) {
            graph[i] = new ArrayList<Integer>();
        }

        for (int i = 0; i < edges.length; i++) {
            graph[edges[i][0]].add(edges[i][1]);
            inDegree.add(edges[i][1]);
        }

        int root = 0;
        int count = 0;
        for (int i = 0; i < n; i++) {
            if (!inDegree.contains(i)) {
                root = i;
                count++;
            }
        }

        if (count != 1)
            return false;

        boolean[] visited = new boolean[n];
        if (!dfs(graph, root, visited)) {
            return false;
        }

        return true;
    }

    private boolean dfs(List<Integer>[] graph, int i, boolean[] visited) {
        
        // 发现环或一child多个parents
        if (visited[i]) {
            return false;
        }
        visited[i] = true;

        for (int num : graph[i]) {
            if (!dfs(graph, num, visited)) {
                return false;
            }
        }

        return true;
    }          
}
相关文章
相关标签/搜索