leetcode
leetcode 201 ~ 250
以图判树

以图判树

难度:

标签:

题目描述

代码结果

运行时间: 18 ms, 内存: 17.2 MB


/*
 * 使用Java Stream的题解代码和注释
 * 题目:以图判树
 * 解题思路:
 * 1. 如果图的边数不等于节点数减一,则直接返回false。
 * 2. 使用Union-Find数据结构检查是否存在环。
 * 3. 检查图的连通性。
 */
import java.util.stream.IntStream;
public class Solution {
    public boolean validTree(int n, int[][] edges) {
        if (edges.length != n - 1) return false;
        int[] parent = IntStream.range(0, n).toArray();
        for (int[] edge : edges) {
            int root1 = find(parent, edge[0]);
            int root2 = find(parent, edge[1]);
            if (root1 == root2) return false;
            parent[root1] = root2;
        }
        return true;
    }
    private int find(int[] parent, int p) {
        while (p != parent[p]) {
            parent[p] = parent[parent[p]]; // 路径压缩
            p = parent[p];
        }
        return p;
    }
}

解释

方法:

该题解使用了并查集来判断给定的边集是否构成一棵树。并查集是一种树形数据结构,用于处理不相交集合的合并及查询所属集合等操作。通过并查集,我们可以高效地判断图中是否存在环以及连通分量的个数。 具体思路如下: 1. 首先,树中边的数量必须等于节点数减一,否则一定不是树。 2. 接着,初始化一个大小为 n 的并查集,每个节点各自为一个集合。 3. 遍历所有的边,对于每条边 (A, B),找到 A 和 B 所在集合的根节点。 - 如果 A 和 B 在同一个集合中,说明出现了环,不是树,返回 false。 - 如果 A 和 B 不在同一个集合中,则将它们所在的集合合并为一个集合。 4. 遍历完所有的边后,如果没有出现环,说明是一棵树,返回 true。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在并查集的实现中,为什么选择了未优化的 find 和 union 方法,而没有使用路径压缩或按秩合并这些常用的优化技术?
在本题的上下文中,选择未优化的 find 和 union 方法是因为问题规模通常较小,且操作的复杂度可以接受。使用未优化的方法简化了代码的实现,使得代码更易于理解和维护。尽管路径压缩或按秩合并可以显著提高并查集操作的效率,特别是在大规模数据或多次查询和合并操作的场景中,但在本题中,由于边的数量与节点数相近且操作次数有限,这些优化可能不会带来显著的性能提升。
🦆
代码中提到如果两个节点已在同一个集合中则表示存在环,这种方法是否能准确处理所有图的情况,即使图是非连通的?
在本题的上下文中,代码先检查边的数量是否等于节点数减一。如果条件满足,随后使用并查集检查是否存在环。此方法在处理连通图时是有效的,因为一个没有环的连通图正是一棵树。然而,如果图是非连通的,即使没有环,边的数量与节点数减一的条件也会导致算法返回 false。因此,这种方法只适用于连通图的情况,而题目假设或要求图应当是连通的(即一棵树)。
🦆
在判断一棵树的定义时,除了检查边的数量等于节点数减一,还需要考虑什么条件以确保结构确实是一棵树?
在判断一个结构是否为一棵树时,除了检查边的数量等于节点数减一这一必要条件外,还需要确保图是连通的且没有环。这两个条件可以通过并查集来验证:1) 使用并查集处理所有边,如果任何两个节点已经在同一集合中再次合并,表明存在环;2) 在处理完所有边后,如果所有节点都属于同一连通分量,则表明图是连通的。只有同时满足这些条件,结构才是一棵树。
🦆
解法中提到如果边的数量不等于节点数减一就直接返回false,这种做法是否考虑了所有可能的非树结构情况?
这种做法主要是基于树的一个基本特性:在一个包含 n 个节点的树中,必然恰有 n-1 条边。这个条件是树的必要条件之一,但不是充分条件,因为单单边的数量等于节点数减一并不能保证没有环或图是连通的。因此,在这之后,解法还需要检查图是否连通且无环来确保结构真的是一棵树。如果边的数量不符,可以直接判断不是树,这种做法有效地排除了所有边数过多或过少的非树结构情况。

相关问题

课程表

你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1

在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai必须 先学习课程  bi

  • 例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1

请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false

 

示例 1:

输入:numCourses = 2, prerequisites = [[1,0]]
输出:true
解释:总共有 2 门课程。学习课程 1 之前,你需要完成课程 0 。这是可能的。

示例 2:

输入:numCourses = 2, prerequisites = [[1,0],[0,1]]
输出:false
解释:总共有 2 门课程。学习课程 1 之前,你需要先完成​课程 0 ;并且学习课程 0 之前,你还应先完成课程 1 。这是不可能的。

 

提示:

  • 1 <= numCourses <= 2000
  • 0 <= prerequisites.length <= 5000
  • prerequisites[i].length == 2
  • 0 <= ai, bi < numCourses
  • prerequisites[i] 中的所有课程对 互不相同

无向图中连通分量的数目

无向图中连通分量的数目