lintcode-medium-Graph Valid Tree

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

 

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

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

 

判断一个图是不是一棵树,条件是:1. 图中没有环 2. 图中任意两点都是连通的

几种做法:

1. union-find:

又分为quick-union和quick-find,我也不是很熟悉,所以干脆都写下来

2. DFS

3. BFS

 

union-find: quick union

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(n - 1 != edges.length)
            return false;
        
        int[] father = new int[n];
        for(int i = 0; i < n; i++)
            father[i] = i;
        
        for(int i = 0; i < edges.length; i++){
            if(find(father, edges[i][0]) == find(father, edges[i][1]))
                return false;
            
            union(father, edges[i][0], edges[i][1]);
        }
        
        return true;
    }
    
    public void union(int[] father, int node1, int node2){
        father[find(father, node1)] = find(father, node2);
    }
    
    public int find(int[] father, int node1){
        if(father[node1] == node1)
            return node1;
        
        father[node1] = find(father, father[node1]);
        return father[node1];
    }
}

 

union-find: quick find

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(n - 1 != edges.length)
            return false;
        
        int[] father = new int[n];
        for(int i = 0; i < n; i++)
            father[i] = i;
        
        for(int i = 0; i < edges.length; i++){
            if(find(father, edges[i][0]) == find(father, edges[i][1]))
                return false;
            
            union(father, edges[i][0], edges[i][1]);
        }
        
        return true;
    }
    
    public void union(int[] father, int node1, int node2){
        int temp = father[node2];
        for(int i = 0; i < father.length; i++){
            if(father[i] == temp)
                father[i] = father[node1];
        }
        
        return;
    }
    
    public int find(int[] father, int node1){
        return father[node1];
    }
}

 

 DFS:

折腾了好久才写出来……

tip:

如果边的个数多于n - 1,必然有环存在

如果少于n - 1,有环存在则不是一棵树,没有环的话,必然有不连通的节点

等于n - 1的时候,如果有环,必有不连通的节点,只要没有环必然是一棵树

由于dfs函数没有记录走过了多少条边,所以dfs一次之后,还需要检查是否有没到过的节点,如果有说明有不连通的点,则这个图不是一棵树

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(n - 1 != edges.length)
            return false;
        
        if(edges.length == 0 && n == 1)
            return true;
        
        boolean[] visited = new boolean[n];
        
        ArrayList<HashSet<Integer>> graph = new ArrayList<HashSet<Integer>>();
        
        for(int i = 0; i < n; i++)
            graph.add(new HashSet<Integer>());
        
        for(int i = 0; i < edges.length; i++){
            graph.get(edges[i][0]).add(edges[i][1]);
            graph.get(edges[i][1]).add(edges[i][0]);
        }
        
        if(!dfs(graph, visited, 0))
            return false;
        
        for(int i = 0; i < n; i++)
            if(!visited[i])
                return false;
        
        return true;
    }
    
    public boolean dfs(ArrayList<HashSet<Integer>> graph, boolean[] visited, int start){
        if(visited[start])
            return false;
        
        visited[start] = true;
        
        HashSet<Integer> set = graph.get(start);
        
        for(Integer next: set){
            graph.get(next).remove(start);
            if(!dfs(graph, visited, next))
                return false;
        }
        
        return true;
    }
    
}

 

BFS:

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(n - 1 != edges.length)
            return false;
        
        if(edges.length == 0 && n == 1)
            return true;
        
        boolean[] visited = new boolean[n];
        
        ArrayList<HashSet<Integer>> graph = new ArrayList<HashSet<Integer>>();
        for(int i = 0; i < n; i++)
            graph.add(new HashSet<Integer>());
        
        for(int i = 0; i < edges.length; i++){
            graph.get(edges[i][0]).add(edges[i][1]);
            graph.get(edges[i][1]).add(edges[i][0]);
        }
        
        Queue<Integer> queue = new LinkedList<Integer>();
        queue.offer(0);
        
        while(!queue.isEmpty()){
            int temp = queue.poll();
            if(visited[temp])
                return false;
            
            visited[temp] = true;
            HashSet<Integer> neighbor = graph.get(temp);
            
            for(Integer next: neighbor){
                graph.get(next).remove(temp);
                queue.offer(next);
            }
            
        }
        
        for(int i = 0; i < n; i++)
            if(!visited[i])
                return false;
        
        return true;
    }
    
}

 

posted @ 2016-03-22 11:44  哥布林工程师  阅读(155)  评论(0编辑  收藏  举报