LeetCode 题解工作台

统计子树中城市之间最大距离

给你 n 个城市,编号为从 1 到 n 。同时给你一个大小为 n-1 的数组 edges ,其中 edges[i] = [u i , v i ] 表示城市 u i 和 v i 之间有一条双向边。题目保证任意城市之间只有唯一的一条路径。换句话说,所有城市形成了一棵 树 。 一棵 子树 是城市的一个子集…

category

5

题型

code_blocks

5

代码语言

hub

3

相关题

当前训练重点

困难 · 二分·树·traversal

bolt

答案摘要

我们注意到 $n \leq 15$,因此可以考虑使用二进制枚举的方法枚举所有的子树。而子树中节点的最大距离,其实就是子树中两个节点之间的最长路径,也即是树的直径,求解树的直径一般可以使用 DFS 或 BFS,先找到树直径的一个端点,然后再从该端点出发,找到树的另一个端点,这两个端点之间的路径长度就是树的直径。 接下来,我们详细说明具体的代码实现。

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 二分·树·traversal 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

给你 n 个城市,编号为从 1 到 n 。同时给你一个大小为 n-1 的数组 edges ,其中 edges[i] = [ui, vi] 表示城市 ui 和 vi 之间有一条双向边。题目保证任意城市之间只有唯一的一条路径。换句话说,所有城市形成了一棵  。

一棵 子树 是城市的一个子集,且子集中任意城市之间可以通过子集中的其他城市和边到达。两个子树被认为不一样的条件是至少有一个城市在其中一棵子树中存在,但在另一棵子树中不存在。

对于 d 从 1 到 n-1 ,请你找到城市间 最大距离 恰好为 d 的所有子树数目。

请你返回一个大小为 n-1 的数组,其中第 d 个元素(下标从 1 开始)是城市间 最大距离 恰好等于 d 的子树数目。

请注意,两个城市间距离定义为它们之间需要经过的边的数目。

 

示例 1:

输入:n = 4, edges = [[1,2],[2,3],[2,4]]
输出:[3,4,0]
解释:
子树 {1,2}, {2,3} 和 {2,4} 最大距离都是 1 。
子树 {1,2,3}, {1,2,4}, {2,3,4} 和 {1,2,3,4} 最大距离都为 2 。
不存在城市间最大距离为 3 的子树。

示例 2:

输入:n = 2, edges = [[1,2]]
输出:[1]

示例 3:

输入:n = 3, edges = [[1,2],[2,3]]
输出:[2,1]

 

提示:

  • 2 <= n <= 15
  • edges.length == n-1
  • edges[i].length == 2
  • 1 <= ui, vi <= n
  • 题目保证 (ui, vi) 所表示的边互不相同。
lightbulb

解题思路

方法一:二进制枚举 + BFS 或 DFS

我们注意到 n15n \leq 15,因此可以考虑使用二进制枚举的方法枚举所有的子树。而子树中节点的最大距离,其实就是子树中两个节点之间的最长路径,也即是树的直径,求解树的直径一般可以使用 DFS 或 BFS,先找到树直径的一个端点,然后再从该端点出发,找到树的另一个端点,这两个端点之间的路径长度就是树的直径。

接下来,我们详细说明具体的代码实现。

我们先根据数组 edgesedges 构建出邻接表 gg,其中 g[u]g[u] 表示节点 uu 的所有邻接节点。

用一个二进制数 maskmask 表示子树,其中 maskmask 的第 ii 位为 11 表示节点 ii 在子树中,否则表示节点 ii 不在子树中。每个节点都有两种状态,即在子树中或不在子树中,有 nn 个节点,因此一共有 2n2^n 种状态。

接下来,我们在 [1,..2n1][1,..2^n-1] 的范围内枚举子树 maskmask,对于每个子树:

如果 maskmask 的二进制表示中只有一个二进制位为 11,即 mask[1,2,4,8,,2n1]mask \in [1,2,4,8,\cdots,2^{n-1}],则跳过该 maskmask,因为这些 maskmask 表示的子树只有一个节点,不符合题意;

否则,我们找到 maskmask 的二进制表示中最高位的二进制位为 11 的位置,记为 curcur。然后从节点 curcur 出发,通过深度优先搜索或者广度优先搜索,找到树直径的一个端点 nxtnxt,然后我们再从节点 nxtnxt 出发,同样通过深度优先搜索或者广度优先搜索,过程中记录下最大距离 mxmx

当走到最深的节点时,即可得知树的直径。此时我们更新答案数组 ansans,将 ans[mx1]ans[mx-1] 的值加 11。注意,这里是 mx1mx-1,因为题目中的最大距离是从 11 开始计数的。

最后,枚举完所有的子树,返回答案数组 ansans 即可。

时间复杂度 O(2n×n)O(2^n \times n),空间复杂度 O(n)O(n)。其中 nn 为节点个数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution:
    def countSubgraphsForEachDiameter(
        self, n: int, edges: List[List[int]]
    ) -> List[int]:
        def dfs(u: int, d: int = 0):
            nonlocal mx, nxt, msk
            if mx < d:
                mx, nxt = d, u
            msk ^= 1 << u
            for v in g[u]:
                if msk >> v & 1:
                    dfs(v, d + 1)

        g = defaultdict(list)
        for u, v in edges:
            u, v = u - 1, v - 1
            g[u].append(v)
            g[v].append(u)
        ans = [0] * (n - 1)
        nxt = mx = 0
        for mask in range(1, 1 << n):
            if mask & (mask - 1) == 0:
                continue
            msk, mx = mask, 0
            cur = msk.bit_length() - 1
            dfs(cur)
            if msk == 0:
                msk, mx = mask, 0
                dfs(nxt)
                ans[mx - 1] += 1
        return ans
speed

复杂度分析

指标
时间Depends on the final approach
空间Depends on the final approach
psychology

面试官常问的追问

外企场景
  • question_mark

    Look for the candidate's understanding of bitmasking and dynamic programming techniques.

  • question_mark

    Assess the candidate's ability to handle tree traversal efficiently within constraints.

  • question_mark

    Evaluate their ability to optimize the algorithm, especially considering time and space complexity.

warning

常见陷阱

外企场景
  • error

    Not efficiently managing the bitmasking process and trying to iterate through all subsets without considering optimizations.

  • error

    Failing to validate whether a subset forms a connected graph before calculating the maximum distance between cities.

  • error

    Overlooking the importance of dynamic programming in storing precomputed values to avoid redundant calculations.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Increase the number of cities to test the scalability of the solution.

  • arrow_right_alt

    Consider additional constraints such as weighted edges or directed edges to modify the problem.

  • arrow_right_alt

    Modify the problem to count subtrees with a fixed number of cities and a maximum distance limit.

help

常见问题

外企场景

统计子树中城市之间最大距离题解:二分·树·traversal | LeetCode #1617 困难