题目描述

✅ 938. 二叉搜索树的范围和

image-20260929105304971

image-20260929105305404

题意分析

求二叉搜索树中节点值落在闭区间 [low,high] 内的总和,等于任意边界的节点也要计入。树的有序性允许一次排除整棵不可能命中的子树,而不必逐个检查其中节点。

解法:DFS + BST 剪枝

核心思路

[!blue]

定义 dfs(node) 返回以当前节点为根的子树中,所有合格节点的值之和。空子树没有贡献,返回 0;非空节点按它与查询区间的关系分成三种情况。

若 node.val < low,当前节点不合格,左子树所有值还更小,也都小于 low,所以当前节点和整棵左子树的贡献都是零,只需返回右子树的查询结果。若 node.val > high,同理排除当前节点和整棵右子树,只搜索左子树。

若当前值位于区间内,就计入它,再加上左右子树各自的查询结果。此时不能直接把整棵子树都计入,因为更小的后代仍可能低于 low,更大的后代也可能高于 high,需要继续按同一规则筛选。

三种情况覆盖了全部可能:剪掉的子树确定没有贡献,保留的左右子树与当前节点互不重叠。只要递归正确返回较小子树的区间和,就能组合出当前子树的正确答案;递归最终到达空节点,因此既不漏算也不重复累加。

解题步骤

  1. 空节点返回零。
  2. 当前值小于下界时,只递归右子树。
  3. 当前值大于上界时,只递归左子树。
  4. 否则累加当前值与两侧区间和。

没有节点落入区间时,各分支最终返回的都是零;查询包含全树值域时,所有节点都会计入。即使 low==high,严格的越界判断也会保留恰好等于该值的节点。

代码实现

class Solution {
    public int rangeSumBST(TreeNode root, int low, int high) {
        return dfs(root, low, high);
    }

    private int dfs(TreeNode node, int low, int high) {
        if (node == null) {
            return 0;
        }

        // 当前值小于下界,左子树只会更小,整棵跳过。
        if (node.val < low) {
            return dfs(node.right, low, high);
        }

        // 当前值大于上界,右子树只会更大,整棵跳过。
        if (node.val > high) {
            return dfs(node.left, low, high);
        }

        return node.val + dfs(node.left, low, high) + dfs(node.right, low, high);
    }
}
func rangeSumBST(root *TreeNode, low int, high int) int {
    if root == nil {
        return 0
    }
    // 当前值小于下界,左子树只会更小,整棵跳过。
    if root.Val < low {
        return rangeSumBST(root.Right, low, high)
    }
    // 当前值大于上界,右子树只会更大,整棵跳过。
    if root.Val > high {
        return rangeSumBST(root.Left, low, high)
    }
    return root.Val + rangeSumBST(root.Left, low, high) + rangeSumBST(root.Right, low, high)
}

复杂度分析

  • 时间复杂度:设区间内节点数为 k、树高为 h,访问量为 $O(k+h)$。合格节点各访问一次,区间外仍被访问的节点位于查找两个边界的路径上;最坏仍为 $O(n)$。
  • 空间复杂度:$O(h)$,用于递归调用栈;退化成链时最坏为 $O(n)$。

关键点总结

[!green]

  • 剪枝依据是整棵子树的值域,不只是一个孩子。
  • 区间包含两端,等于 low 或 high 的节点必须计入。
  • 返回值统一表示当前子树的有效总和。

易错点总结

[!yellow]

  • 用 <=low 或 >=high 排除节点,会漏掉闭区间边界。
  • 越界时只返回可能命中一侧的递归结果,不能再加入当前节点值。
  • 当前节点合格不代表全部后代合格,两侧仍需递归判断。

相似题目

题目 难度 关联与区别
669. 修剪二叉搜索树 中等 同样利用BST范围关系剪掉不可能贡献的子树,原题修改树,本题只累计范围内节点值。
700. 二叉搜索树中的搜索 简单 点查找扩展成区间查询,当前值小于下界时只需查右子树,大于上界时只需查左子树。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2022/47428036
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!