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. poj1679The Unique MST(次小生成树模板)

    次小生成树模板,别忘了判定不存在最小生成树的情况 #include <iostream> #include <cstdio> #include <cstring> ...

  2. python笔记37-史上最好用的发邮件zmail

    简介 python发邮件之前用的是smtplib,代码太过于复杂,学习成本大,并且很多人学不会.之前专门写过一篇https://www.cnblogs.com/yoyoketang/p/7277259 ...

  3. 常用conda命令【转载】

    转载地址:https://haoyu.love/blog900.html 一直在用 Conda,很多东西记不住,每次都要查 Doc.那好,就写在这里做个备忘好了. 在 bash 里面自动加载 cond ...

  4. 《逆袭团队》第九次团队作业【Beta】Scrum meeting 3

    项目 内容 软件工程 任课教师博客主页链接 作业链接地址 团队作业9:Beta冲刺与团队项目验收 团队名称 逆袭团队 具体目标 (1)掌握软件黑盒测试技术:(2)学会编制软件项目总结PPT.项目验收报 ...

  5. treegrid 折叠全部节点

    $(".easyui-treegrid").treegrid({ url: '@Url.Action("GetDataDictionaryList", &quo ...

  6. centos7部署inotify与rsync实现实时数据同步

    实验环境:CentOS Linux release 7.6.1810 node1:192.168.216.130 客户端(向服务端发起数据同步) node2:192.168.216.132 服务端(接 ...

  7. Linux中的CentOS 6克隆之后修改

    Centos6 克隆后的简单的网络配置 第一步:修改主机名 $ vi /etc/sysconfig/network     第二步: $ vi  /etc/udev/rules.d/70-persis ...

  8. [Codeforces Educational Round 71]Div. 2

    总结 手速场...像我这种没手速的就直接炸了... 辣鸡 E 题交互,少打了个 ? 调了半个小时... 到最后没时间 G 题题都没看就结束了...结果早上起来被告知是阿狸的打字机...看了看题一毛一样 ...

  9. git的搭建和使用

    目录: 1.git与github介绍2.下载安装Git-20-64-bit.exe3.Git常用命令 git与github介绍 Git是什么 Git是一个开源的[分布式][版本控制系统],用于敏捷高效 ...

  10. WinDbg扩展

    WinDbg的扩展,也可以叫插件.它用于实现针对特定调试目标的调试功能,用于扩展某一方面的调试功能.扩展的实现是通过扩展模块(DLL)实现的.Windbg本身已经包含了很多扩展命令,这些扩展为这Win ...