这是 LeetCode 2440. Create Components With Same Value(创建价值相同的连通块)的 Python3 实现。

题目理解

给定一棵无向树,每个节点有一个值 `nums[i]`。可以删除一些边,将树分成多个连通块。要求每个连通块的价值(块内所有节点值之和)相等。返回最多可以删除多少条边(即连通块数减1)。

核心思路

关键观察:
- 设总和为 `s`,分成 `k` 个连通块,则每个块的价值必须是 `s / k`
- 删除的边数 = `k - 1`,所以要最大化删除边数,就要最大化 `k`
- `k` 的最大可能值受限于:每个块至少包含一个节点,且每个块的价值至少为 `max(nums)`,所以 `k <= min(n, s / max(nums))`

算法:
1. 从大到小枚举连通块数量 `k`
2. 对于每个 `k`,检查 `s % k == 0`,则目标价值 `t = s // k`
3. 用 DFS 自底向上计算每个子树的和:
   - 如果子树和恰好等于 `t`,说明可以在此处切断,返回 0(表示子树和已清零)
   - 如果子树和大于 `t`,说明无法分割,返回 -1
   - 否则返回子树和,继续向上累积
4. 如果根节点返回 0,说明可以成功分成 `k` 块,返回 `k - 1`

Python3 代码

```python
from typing import List
from collections import defaultdict

class Solution:
    def componentValue(self, nums: List[int], edges: List[List[int]]) -> int:
        def dfs(i: int, fa: int) -> int:
            """
            返回以i为根的子树的累积和
            - 如果子树和恰好等于t,返回0(表示可以在此处切断)
            - 如果子树和大于t,返回-1(表示无法分割)
            - 否则返回子树和,继续向上累积
            """
            x = nums[i]
            for j in g[i]:
                if j != fa:
                    y = dfs(j, i)
                    if y == -1:  # 子树无法分割
                        return -1
                    x += y
            if x > t:  # 累积和超过目标值,无法分割
                return -1
            # 如果恰好等于目标值,返回0(切断);否则返回累积和
            return x if x < t else 0

        n = len(nums)
        # 构建邻接表
        g = defaultdict(list)
        for a, b in edges:
            g[a].append(b)
            g[b].append(a)
        
        s = sum(nums)           # 总和
        mx = max(nums)          # 最大值
        
        # 从大到小枚举连通块数量k
        # k的上限:每个块至少一个节点(n),且每个块价值至少为mx (s//mx)
        for k in range(min(n, s // mx), 1, -1):
            if s % k == 0:      # 必须能整除
                t = s // k      # 每个连通块的目标价值
                if dfs(0, -1) == 0:  # 根节点返回0,表示成功分割
                    return k - 1  # 删除的边数 = 连通块数 - 1
        
        return 0  # 无法分割,删除0条边
```

复杂度分析

项目    复杂度    
时间    O(n × √s) — 枚举 `k` 的因子,每次 DFS 遍历整棵树    
空间    O(n) — 邻接表和递归栈空间    

其中 `n <= 2 × 10^4`,`nums[i] <= 50`,所以 `s <= 10^6`,完全可以通过。

 

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐