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; } }