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]]
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:
- 邊界問題檢測:題目要求為能否構成一棵有效的樹,若邊集為空,有以下情況:
- 只有一個節點:可以構成一棵有效的樹
- 有一個以上的節點:因為沒有邊。所以存在離散的節點,所以不能構成一棵有效的樹
- 沒有節點:空樹
- 如果存在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時,一定有環出現。
所以上面代碼應該可以更簡潔一點?
Graph Valid Tree