1530. 好叶子节点对的数量

目录

🌲 LeetCode 好叶子节点对的数量(Python详解)

📘 题目描述

🎯 示例

📈 解题分析

目标:

注意点:

🧠 解题思路

关键步骤:

🔧 代码实现(Python)

📊 分析与比较

🧪 更多示例

示例 2:

示例 3:

✨ 总结

🔑 技巧回顾:


🌲 LeetCode 好叶子节点对的数量(Python详解)

📘 题目描述

给你一棵二叉树的根节点 root 和一个整数 distance

如果二叉树中两个 叶子节点 之间的最短路径长度 小于或等于 distance,那么这两个叶子节点可以构成一组 "好叶子节点对"。

请你返回 二叉树中好叶子节点对的数量


🎯 示例

输入:

root = [1,2,3,null,4]
distance = 3

输出:

1

解释:

树结构如下:

    1
   / \
  2   3
   \
    4
  • 叶子节点为 43
  • 43 的最短路径是:4 → 2 → 1 → 3,共 3 条边。
  • 因为路径长度等于 distance=3,所以是一组好叶子节点对。

📈 解题分析

目标:

统计所有满足条件的叶子节点对(两两之间的路径长度不超过 distance)。

注意点:

  • “路径长度” 指的是节点之间边的数量,而不是节点数量。
  • 要求 遍历所有叶节点对,并统计符合条件的对数。
  • 暴力法会超时,因此需要 自底向上的深度优先搜索(DFS) + 剪枝

🧠 解题思路

我们使用 DFS 递归的方法来遍历二叉树,并在每个节点向上返回它子树中所有叶节点到当前节点的路径长度(以数组形式记录)。

关键步骤:

  1. 定义返回值
    • 每个节点向上传递一个数组 dist,其中 dist[i] 表示从当前节点出发距离为 i+1 的叶子节点数量。
  1. 统计好叶子对
    • 对于当前节点,组合左右子树返回的 dist 数组:
      • 遍历 left[i]right[j]
      • i + j + 2 <= distance(+2 是因为路径从左子树叶到右子树叶要经过当前节点的两个边),则这是一组好叶子节点对。
  1. 构造合并后的数组向上传递
    • 将左右子树中所有叶节点的距离加一(因为当前节点到它们的距离多了一层)。
    • 超出 distance 的距离可剪枝。

🔧 代码实现(Python)

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution:
    def countPairs(self, root: Optional[TreeNode], distance: int) -> int:
        self.ans = 0

        def dfs(node):
            if not node:
                return [0] * distance
            if not node.left and not node.right:
                dist = [0] * distance
                dist[0] = 1
                return dist

            left = dfs(node.left)
            right = dfs(node.right)

            # 统计左右子树之间的好叶子节点对
            for i in range(distance):
                for j in range(distance):
                    if i + j + 2 <= distance:
                        self.ans += left[i] * right[j]

            # 构建向上传递的距离数组
            merged = [0] * distance
            for i in range(distance - 1):
                merged[i + 1] = left[i] + right[i]
            return merged

        dfs(root)
        return self.ans

📊 分析与比较

方法

时间复杂度

空间复杂度

是否超时

可读性

暴力法

O(n²)(枚举所有叶子节点对)

O(n)

会超时

简单但低效

DFS + 剪枝(当前方法)

O(n * d²)(每个节点比较 d² 次)

O(d)

✅ 不超时

✅ 高效且直观

说明:

  • n 是二叉树中的节点数。
  • ddistance 的值(最大为10,根据题目约束)。
  • 由于 distance 很小, 是常量,因此 DFS 方法在实际中表现优异。

🧪 更多示例

示例 2:

root = [1]
distance = 1

输出:0
说明: 只有一个节点,无叶子对。


示例 3:

root = [1,2,3,4,5,null,6]
distance = 3

树结构如下:

       1
      / \
     2   3
    / \    \
   4   5    6

叶子节点为:[4, 5, 6]。满足条件的对有:

  • 4 & 5:路径为 4→2→5,距离2
  • 5 & 6:路径为 5→2→1→3→6,距离4(不满足)
  • 4 & 6:路径为 4→2→1→3→6,距离4(不满足)

输出:1


✨ 总结

本题考查的是树的递归遍历与路径问题。通过深度优先搜索,我们可以有效地自底向上收集叶子节点的距离信息,并在遍历过程中完成对符合条件的叶子节点对的统计。

🔑 技巧回顾:

  • 自底向上的 DFS 可用于统计叶子到当前节点的路径。
  • 利用数组 dist 优雅处理距离分布。
  • 注意剪枝:数组只保留到 distance 的信息,防止爆炸式递归。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值