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.

Example 1:

Input: n = 5, and edges = [[0,1], [0,2], [0,3], [1,4]]
Output: true

Example 2:

Input: n = 5, and edges = [[0,1], [1,2], [2,3], [1,3], [1,4]]
Output: 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.

这道题给了一个无向图,让我们来判断其是否为一棵树,如果是树的话,所有的节点必须是连接的,也就是说必须是连通图,而且不能有环,所以焦点就变成了验证是否是连通图和是否含有环。首先用 DFS 来做,根据 pair 来建立一个图的结构,用邻接链表来表示,还需要一个一位数组v来记录某个结点是否被访问过,然后用 DFS 来搜索结点0,遍历的思想是,当 DFS 到某个结点,先看当前结点是否被访问过,如果已经被访问过,说明环存在,直接返回 false,如果未被访问过,现在将其状态标记为已访问过,然后到邻接链表里去找跟其相邻的结点继续递归遍历,注意还需要一个变量 pre 来记录上一个结点,以免回到上一个结点,这样遍历结束后,就把和结点0相邻的节点都标记为 true,然后再看v里面是否还有没被访问过的结点,如果有,则说明图不是完全连通的,返回 false,反之返回 true,参见代码如下:

解法一:

// 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, , -)) 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;
}
};

下面来看 BFS 的解法,思路很相近,需要用 queue 来辅助遍历,这里没有用一维向量来标记节点是否访问过,而是用了一个 HashSet,如果遍历到一个节点,在 HashSet 中没有,则加入 HashSet,如果已经存在,则返回false,还有就是在遍历邻接链表的时候,遍历完成后需要将结点删掉,参见代码如下:

解法二:

// 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{{}};
queue<int> q{{}};
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;
}
};

我们再来看 Union Find 的方法,这种方法对于解决连通图的问题很有效,思想是遍历节点,如果两个节点相连,将其 roots 值连上,这样可以找到环,初始化 roots 数组为 -1,然后对于一个 pair 的两个节点分别调用 find 函数,得到的值如果相同的话,则说明环存在,返回 false,不同的话,将其 roots 值 union 上,参见代码如下:

解法三:

// Union Find
class Solution {
public:
bool validTree(int n, vector<pair<int, int>>& edges) {
vector<int> roots(n, -);
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 - ;
}
int find(vector<int> &roots, int i) {
while (roots[i] != -) i = roots[i];
return i;
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/261

类似题目:

Number of Islands II

Number of Connected Components in an Undirected Graph

参考资料:

https://leetcode.com/problems/graph-valid-tree/

https://leetcode.com/problems/graph-valid-tree/discuss/69018/AC-Java-Union-Find-solution

https://leetcode.com/problems/graph-valid-tree/discuss/69042/AC-Java-Graph-DFS-solution-with-adjacency-list

https://leetcode.com/problems/graph-valid-tree/discuss/69019/Simple-and-clean-c%2B%2B-solution-with-detailed-explanation.

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Graph Valid Tree 图验证树的更多相关文章

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

  2. 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), ...

  3. LeetCode Graph Valid Tree

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

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

  5. [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), ...

  6. 图是否是树 · Graph Valid Tree

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

  7. [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 ...

  8. Graph Valid Tree -- LeetCode

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

  9. [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 ...

随机推荐

  1. Properties操作指南

    一.简介: Properties是java中用的比较多的一个类,表示一个持久的属性集.继承于Hashtable,Properties可从流中加载,也可保存在流中.属性列表中每个键极其对应值共同组成一个 ...

  2. 【分布式】Zookeeper系统模型

    一.前言 前面已经讲解了Zookeeper的一些应用场景,但是并没有深入到Zookeeper内部进行分析,本篇将讲解其系统模型. 二.系统模型 2.1 数据模型 Zookeeper的数据节点称为ZNo ...

  3. Windows下Git多账号配置,同一电脑多个ssh-key的管理

    这一篇文章是对上一篇文章<Git-TortoiseGit完整配置流程>的拓展,所以需要对上一篇文章有所了解,当然直接往下看也可以,其中也有一些提到一些基础的操作. <Git-Tort ...

  4. JavaScript学习(一) —— 环境搭建与JavaScript初探

    1.开发环境搭建 本系列教程的开发工具,我们采用HBuilder. 可以去网上下载最新的版本,然后解压一下就能直接用了.学习JavaScript,环境搭建是非常简单的,或者说,只要你有一个浏览器,一个 ...

  5. 基于WebGL 的3D呈现A* Search Algorithm

    http://www.hightopo.com/demo/astar/astar.html 最近搞个游戏遇到最短路径的常规游戏问题,一时起兴基于HT for Web写了个A*算法的WebGL 3D呈现 ...

  6. C# WCF服务端搭建和客户端调用

    1) 打开Visual Studio 2012,在菜单上点击文件->新建->项目->WCF服务应用程序.在弹出界面的"名称"对应的文本框中输入"WcfS ...

  7. Qt安装配置

    Qt Creator: 下载: Qt 5.5.1 for Windows 32-bit(MinGW 4.9.2, 1.0 GB):http://download.qt.io/official_rele ...

  8. wpf 列表、菜单 收起与展开,通过Grid DoubleAnimation或者Expander实现

    菜单收缩有很多种方法具体如何实现还是看个人想法: 第一种通过后台控制收起与展开: 效果图: 代码 : <Grid> <Grid.ColumnDefinitions> <C ...

  9. PHP函数基础知识.png

  10. Lind.DDD.SSO单点登陆组件的使用(原创)

    回到目录 一般sso的说明 在Lind.DDD框架里,有对单点登陆的集成,原理就是各个网站去sso网站统一登陆授权,之后在sso网站将登陆的token进行存储,存储方式随你(cache,redis,m ...