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.

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.

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.

解题思路:

判断给出的点和边构成的图是否为一个树,可以认为是判断图中有无环的存在,可以使用并查集(union find)来进行解答。

本题中的图为无向图, 即[0,1]和[1,0]为同一条边,为了方便寻找唯一根结点,在union的过程中,将值较大的父亲值设置为值较小的父亲,即:

if(a < b) parent[rootB] = rootA; else parent[rootA] = rootB;

 

我遇见的bug:

  1. 边界问题检测:题目要求为能否构成一棵有效的树,若边集为空,有以下情况:
    • 只有一个节点:可以构成一棵有效的树
    • 有一个以上的节点:因为没有边。所以存在离散的节点,所以不能构成一棵有效的树
    • 没有节点:空树
  2. 如果存在n个节点,若要把n个节点连接起来,至少需要n-1条边。若边的条数少于n-1,则无法链接所有节点,不能构成一颗有效的树
public class Solution {
    /**
     * @param n: An integer
     * @param edges: a list of undirected edges
     * @return: true if it's a valid tree, or false
     */
    public boolean validTree(int n, int[][] edges) {
        // write your code here
        if(edges.length == 0 && n > 1)
            return false;
        if(n == 0 || (edges.length == 0 && n == 1))
            return true;
        if(edges.length < n-1)
            return false;
        int[] parent = new int[n];
        for(int i = 0; i < n; i++){
            parent[i] = i;
        }
        for(int i = 0; i < edges.length; i++){
            if(!union(parent, edges[i][0], edges[i][1]))
                return false;
            
        }
        int root = find(parent, 0);
        for(int i = 0; i < n; i++){
            if(find(parent, i) != root)
                return false;
        }
        return true;
    }
    private int find(int[] parent, int a){
        if(parent[a] == a)
            return a;
        return parent[a] = find(parent, parent[a]);
    }
    private boolean union(int[] parent, int a, int b){
        int rootA = find(parent, a);
        int rootB = find(parent, b);
        if(rootA != rootB){
            if(a < b)
                parent[rootB] = rootA;
            else
                parent[rootA] = rootB;
            return true;
        }
        return false;
    }
}

突然想到:

当边数等于n-1时,可能出现一棵有效的树,此时无环,若存在环,则一定有孤立的点。

当边数大于n-1时,一定有环出现。

所以上面代码应该可以更简洁一点?

原文地址:https://www.cnblogs.com/yaoyudadudu/p/8732302.html