• [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

    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.

    以图判树。

    给定从 0 到 n-1 标号的 n 个结点,和一个无向边列表(每条边以结点对来表示),请编写一个函数用来判断这些边是否能够形成一个合法有效的树结构。

    注意:你可以假定边列表 edges 中不会出现重复的边。由于所有的边是无向边,边 [0,1] 和边 [1,0] 是相同的,因此不会同时出现在边列表 edges 中。

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/graph-valid-tree
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    这道题属于图和树的综合题。给的input是节点的个数n和一些边edges,请你判断能否组成一棵树。有一个概念需要复习,树和图的区别在于图是可以有环 (cycle) 的,树不能有环;同时图的节点有可能不会连在一片,但是树的所有节点必定都是相连成一片的。对于这道题,有一些corner case需要特判,如果只有一个节点的话,那么就一定没有edges;因为题设说了不会给额外的边,所以如果边的数量 != 节点数量 - 1的话,一定不是树。

    照着这个思路,我还是提供三种做法,BFS, DFS和Union Find。三种做法的时间空间复杂度都一样,union find在运行时间上可以通过路径压缩变得更快。

    BFS

    时间O(V * E)

    空间O(n)

    Java实现

     1 class Solution {
     2     public boolean validTree(int n, int[][] edges) {
     3         // create graph
     4         List<List<Integer>> graph = new ArrayList<>();
     5         for (int i = 0; i < n; i++) {
     6             graph.add(new ArrayList<>());
     7         }
     8         for (int i = 0; i < edges.length; i++) {
     9             graph.get(edges[i][0]).add(edges[i][1]);
    10             graph.get(edges[i][1]).add(edges[i][0]);
    11         }
    12 
    13         boolean[] visited = new boolean[n];
    14         Queue<Integer> queue = new LinkedList<>();
    15         queue.offer(0);
    16         while (!queue.isEmpty()) {
    17             int cur = queue.poll();
    18             if (visited[cur] == true) {
    19                 return false;
    20             }
    21             visited[cur] = true;
    22             for (int nei : graph.get(cur)) {
    23                 if (!visited[nei]) {
    24                     queue.offer(nei);
    25                 }
    26             }
    27         }
    28 
    29         for (int i = 0; i < n; i++) {
    30             if (visited[i] == false) {
    31                 return false;
    32             }
    33         }
    34         return true;
    35     }
    36 }

    DFS

    时间O(V * E)

    空间O(n)

    Java实现

     1 class Solution {
     2     public boolean validTree(int n, int[][] edges) {
     3         // create graph
     4         List<List<Integer>> g = new ArrayList<>();
     5         for (int i = 0; i < n; i++) {
     6             g.add(new ArrayList<>());
     7         }
     8         for (int[] e : edges) {
     9             g.get(e[0]).add(e[1]);
    10             g.get(e[1]).add(e[0]);
    11         }
    12 
    13         HashSet<Integer> visited = new HashSet<>();
    14         visited.add(0);
    15         boolean res = helper(g, visited, 0, -1);
    16         if (res == false) {
    17             return false;
    18         }
    19         return visited.size() == n ? true : false;
    20     }
    21 
    22     private boolean helper(List<List<Integer>> g, HashSet<Integer> visited, int cur, int parent) {
    23         List<Integer> neighbors = g.get(cur);
    24         for (int nei : neighbors) {
    25             if (nei == parent) {
    26                 continue;
    27             }
    28             // cycle
    29             if (visited.contains(nei)) {
    30                 return false;
    31             }
    32             visited.add(nei);
    33             boolean res = helper(g, visited, nei, cur);
    34             if (res == false) {
    35                 return false;
    36             }
    37         }
    38         return true;
    39     }
    40 }

    Union Find

    时间O(V * E)

    空间O(n)

    Java实现

     1 class Solution {
     2     public boolean validTree(int n, int[][] edges) {
     3         // corner case
     4         if (n == 1 && edges.length == 0) {
     5             return true;
     6         }
     7         if (n < 1 || edges == null || edges.length != n - 1) {
     8             return false;
     9         }
    10 
    11         // normal case
    12         int[] roots = new int[n];
    13         for (int i = 0; i < n; i++) {
    14             roots[i] = -1;
    15         }
    16 
    17         for (int[] pair : edges) {
    18             int x = find(roots, pair[0]);
    19             int y = find(roots, pair[1]);
    20             if (x == y) {
    21                 return false;
    22             }
    23             roots[x] = y;
    24         }
    25         return true;
    26     }
    27 
    28     private int find(int[] roots, int i) {
    29         while (roots[i] != -1) {
    30             i = roots[i];
    31         }
    32         return i;
    33     }
    34 }

    相关题目

    261. Graph Valid Tree

    323. Number of Connected Components in an Undirected Graph

    547. Friend Circles

    LeetCode 题目总结

  • 相关阅读:
    简单讲解Asp.Net Core自带IOC容器ServiceCollection
    C#配置文件configSections详解
    学习Linq之前必须知道的几种语法糖
    学习Linq之前必须要了解的扩展方法
    学习学习学习学习!!!!!!!!!!!!
    SpringBoot自动配置原理
    OAuth2
    微服务搭建学习笔记(一) 认证中心搭建
    Vue 学习记录
    Vue实例(1)
  • 原文地址:https://www.cnblogs.com/cnoodle/p/14199807.html
Copyright © 2020-2023  润新知