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.

Hint:

  1. Given n = 5 and edges = [[0, 1], [1, 2], [3, 4]], what should your return? Is this case a valid tree?
  2. According to the definition of tree on Wikipedia: “a tree is an undirected graph in which any two vertices are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.”

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.

给一个无向图,判断其是否为一棵树。如果是树的话,所有的节点必须是连接的,也就是说必须是连通图,而且不能有环,所以就变成了验证是否是连通图和是否含有环。

解法1: DFS

解法2: BFS

解法3: Union Find

Java: DFS

public boolean validTree(int n, int[][] edges) {
HashMap<Integer, ArrayList<Integer>> map = new HashMap<Integer, ArrayList<Integer>>();
for(int i=0; i<n; i++){
ArrayList<Integer> list = new ArrayList<Integer>();
map.put(i, list);
} for(int[] edge: edges){
map.get(edge[0]).add(edge[1]);
map.get(edge[1]).add(edge[0]);
} boolean[] visited = new boolean[n]; if(!helper(0, -1, map, visited))
return false; for(boolean b: visited){
if(!b)
return false;
} return true;
} public boolean helper(int curr, int parent, HashMap<Integer, ArrayList<Integer>> map, boolean[] visited){
if(visited[curr])
return false; visited[curr] = true; for(int i: map.get(curr)){
if(i!=parent && !helper(i, curr, map, visited)){
return false;
}
} return true;
} 

Java: BFS

public boolean validTree(int n, int[][] edges) {
HashMap<Integer, ArrayList<Integer>> map = new HashMap<Integer, ArrayList<Integer>>();
for(int i=0; i<n; i++){
ArrayList<Integer> list = new ArrayList<Integer>();
map.put(i, list);
} for(int[] edge: edges){
map.get(edge[0]).add(edge[1]);
map.get(edge[1]).add(edge[0]);
} boolean[] visited = new boolean[n]; LinkedList<Integer> queue = new LinkedList<Integer>();
queue.offer(0);
while(!queue.isEmpty()){
int top = queue.poll();
if(visited[top])
return false; visited[top]=true; for(int i: map.get(top)){
if(!visited[i])
queue.offer(i);
}
} for(boolean b: visited){
if(!b)
return false;
} return true; 

Java: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) {
if (n == 0) {
return false;
} if (edges.length != n - 1) {
return false;
} Map<Integer, Set<Integer>> graph = initializeGraph(n, edges); // bfs
Queue<Integer> queue = new LinkedList<>();
Set<Integer> hash = new HashSet<>(); queue.offer(0);
hash.add(0);
while (!queue.isEmpty()) {
int node = queue.poll();
for (Integer neighbor : graph.get(node)) {
if (hash.contains(neighbor)) {
continue;
}
hash.add(neighbor);
queue.offer(neighbor);
}
} return (hash.size() == n);
} private Map<Integer, Set<Integer>> initializeGraph(int n, int[][] edges) {
Map<Integer, Set<Integer>> graph = new HashMap<>();
for (int i = 0; i < n; i++) {
graph.put(i, new HashSet<Integer>());
} for (int i = 0; i < edges.length; i++) {
int u = edges[i][0];
int v = edges[i][1];
graph.get(u).add(v);
graph.get(v).add(u);
} return graph;
}
}

Java: Union Find  

public class Solution {
class UnionFind{
HashMap<Integer, Integer> father = new HashMap<Integer, Integer>();
UnionFind(int n){
for(int i = 0 ; i < n; i++) {
father.put(i, i);
}
}
int compressed_find(int x){
int parent = father.get(x);
while(parent!=father.get(parent)) {
parent = father.get(parent);
}
int temp = -1;
int fa = father.get(x);
while(fa!=father.get(fa)) {
temp = father.get(fa);
father.put(fa, parent) ;
fa = temp;
}
return parent; } void union(int x, int y){
int fa_x = compressed_find(x);
int fa_y = compressed_find(y);
if(fa_x != fa_y)
father.put(fa_x, fa_y);
}
}
/**
* @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) {
// tree should have n nodes with n-1 edges
if (n - 1 != edges.length) {
return false;
} UnionFind uf = new UnionFind(n); for (int i = 0; i < edges.length; i++) {
if (uf.compressed_find(edges[i][0]) == uf.compressed_find(edges[i][1])) {
return false;
}
uf.union(edges[i][0], edges[i][1]);
}
return true;
}
}  

Python: DFS

class Solution(object):
def validTree(self, n, edges):
lookup = collections.defaultdict(list)
for edge in edges:
lookup[edge[0]].append(edge[1])
lookup[edge[1]].append(edge[0])
visited = [False] * n if not self.helper(0, -1, lookup, visited):
return False for v in visited:
if not v:
return False return True def helper(self, curr, parent, lookup, visited):
print curr, visited
if visited[curr]:
return False
visited[curr] = True
for i in lookup[curr]:
if (i != parent and not self.helper(i, curr, lookup, visited)):
return False return True if __name__ == '__main__':
print Solution().validTree(5, [[0, 1], [0, 2], [0, 3], [1, 4]])
print Solution().validTree(5, [[0, 1], [1, 2], [2, 3], [1, 3], [1, 4]]) 

Python: BFS, Time: O(|V| + |E|), Space: O(|V| + |E|)

class Solution(object):
# @param {integer} n
# @param {integer[][]} edges
# @return {boolean}
def validTree(self, n, edges):
if len(edges) != n - 1: # Check number of edges.
return False # init node's neighbors in dict
neighbors = collections.defaultdict(list)
for u, v in edges:
neighbors[u].append(v)
neighbors[v].append(u) # BFS to check whether the graph is valid tree.
visited = {}
q = collections.deque([0])
while q:
curr = q.popleft()
visited[curr] = True
for node in neighbors[curr]:
if node not in visited:
visited[node] = True
q.append(node) return len(visited) == n

Python: Union Find

class Solution:
# @param {int} n an integer
# @param {int[][]} edges a list of undirected edges
# @return {boolean} true if it's a valid tree, or false
def validTree(self, n, edges):
# Write your code here
root = [i for i in range(n)]
for i in edges:
root1 = self.find(root, i[0])
root2 = self.find(root, i[1])
if root1 == root2:
return False
else:
root[root1] = root2
return len(edges) == n - 1 def find(self, root, e):
if root[e] == e:
return e
else:
root[e] = self.find(root, root[e])
return root[e]  

C++: DFS

class Solution {
public:
bool validTree(int n, vector<pair<int, int>>& edges) {
vector<vector<int>> g(n, vector<int>());
vector<bool> v(n, false);
for (auto a : edges) {
g[a.first].push_back(a.second);
g[a.second].push_back(a.first);
}
if (!dfs(g, v, 0, -1)) return false;
for (auto a : v) {
if (!a) return false;
}
return true;
}
bool dfs(vector<vector<int>> &g, vector<bool> &v, int cur, int pre) {
if (v[cur]) return false;
v[cur] = true;
for (auto a : g[cur]) {
if (a != pre) {
if (!dfs(g, v, a, cur)) return false;
}
}
return true;
}
};

C++: BFS  

class Solution {
public:
bool validTree(int n, vector<pair<int, int>>& edges) {
vector<unordered_set<int>> g(n, unordered_set<int>());
unordered_set<int> s{{0}};
queue<int> q{{0}};
for (auto a : edges) {
g[a.first].insert(a.second);
g[a.second].insert(a.first);
}
while (!q.empty()) {
int t = q.front(); q.pop();
for (auto a : g[t]) {
if (s.count(a)) return false;
s.insert(a);
q.push(a);
g[a].erase(t);
}
}
return s.size() == n;
}
};

C++: Union Find  

class Solution {
public:
bool validTree(int n, vector<pair<int, int>>& edges) {
vector<int> roots(n, -1);
for (auto a : edges) {
int x = find(roots, a.first), y = find(roots, a.second);
if (x == y) return false;
roots[x] = y;
}
return edges.size() == n - 1;
}
int find(vector<int> &roots, int i) {
while (roots[i] != -1) i = roots[i];
return i;
}
};

  

类似题目:  

[LeetCode] 200. Number of Islands 岛屿的数量

[LeetCode] 305. Number of Islands II 岛屿的数量之二

[LeetCode] 323. Number of Connected Components in an Undirected Graph 无向图中的连通区域的个数

All LeetCode Questions List 题目汇总

[LeetCode] 261. Graph Valid Tree 图是否是树的更多相关文章

  1. [LeetCode#261] Graph Valid Tree

    Problem: Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair o ...

  2. [LeetCode] 261. Graph Valid Tree _ Medium tag: BFS

    Given n nodes labeled from 0 to n-1 and a list of undirected edges (each edge is a pair of nodes), w ...

  3. [LeetCode] 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), ...

  4. 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 nod ...

  5. [Locked] Graph Valid Tree

    Graph Valid Tree Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is ...

  6. [Swift]LeetCode261.图验证树 $ 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), ...

  7. LeetCode Graph Valid Tree

    原题链接在这里:https://leetcode.com/problems/graph-valid-tree/ 题目: Given n nodes labeled from 0 to n - 1 an ...

  8. Leetcode: Graph Valid Tree && Summary: Detect cycle in undirected graph

    Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), ...

  9. 图是否是树 · Graph Valid Tree

    [抄题]: 给出 n 个节点,标号分别从 0 到 n - 1 并且给出一个 无向边的列表 (给出每条边的两个顶点), 写一个函数去判断这张`无向`图是否是一棵树. 给出n = 5 并且 edges = ...

随机推荐

  1. Codeforces_Round_547 (Div. 3)题解

    题目链接 传送门 A题 题目 题意 给你两个正整数\(n\)和\(m\),然后你可以进行无数次操作(每次操作可以将\(n\)扩大两倍,或者扩大三倍),问你是否能够得到\(m\). 代码实现如下 n, ...

  2. Thinkphp内核百度小程序输出接口

    最近百度小程序比较火,自己站点用thinkphp打造的,所以写了这个Thinkphp的百度小程序输出接口,实现数据同步. 附上代码 <?php namespace app\article\con ...

  3. django-缓存django-redis

    https://django-redis-chs.readthedocs.io/zh_CN/latest/ 安装 django-redis 最简单的方法就是用 pip : pip install dj ...

  4. Codeforces Round #605 (Div. 3) C. Yet Another Broken Keyboard

    链接: https://codeforces.com/contest/1272/problem/C 题意: Recently, Norge found a string s=s1s2-sn consi ...

  5. Clickhouse 性能瓶颈排查 IO过高

    前几天公司clickhouse 有个查询很慢.经理一直追问为什么慢 是cpu 不够 还是IO 占用太高,还是其他的原因.于是有了以下的排查 执行该条,在不考虑优化sql 的情况下 进行性能排查 1.首 ...

  6. 实训作业6 (数据I/O)

    1. 文件输出流的应用. 定义如下字符串: String str = “12345abcdef@#%&*软件工程”; 编写程序将该字符串写入文件”data.txt”. import java. ...

  7. MySQL 硬链接删除大表

    在清理整个大表时,我们推荐使用drop,而非delete.但是如果表实在太大,即使是drop,也需要消耗一定的时间.这时可以利用linux的硬连接来快速删除大表,操作过程如下:有一个大表test,共有 ...

  8. BZOJ 5507: [gzoi2019]旧词 LCT

    和之前那个 [LNOI]LCA 几乎是同一道题,就是用动态树来维护查分就行. code: #include <bits/stdc++.h> using namespace std; #de ...

  9. pgloader 学习(四)一些简单操作例子

    上边已经说明了pgloader 的基本使用(篇理论),但是对于实际操作偏少,以下是一个简单的操作 不像官方文档那样,我为了方便,直接使用docker-compose 运行,同时这个环境,会在后边大部分 ...

  10. 原创:协同过滤之ALS

    推荐系统的算法,在上个世纪90年代成型,最早应用于UserCF,基于用户的协同过滤算法,标志着推荐系统的形成.首先,要明白以下几个理论:①长尾理论②评判推荐系统的指标.之所以需要推荐系统,是要挖掘冷门 ...