938. Range Sum of BST - Explanation

Problem Link

Description

You are given the root node of a binary search tree and two integers low and high, return the sum of values of all nodes with a value in the inclusive range [low, high].

Example 1:

Input: root = [5,3,8,1,4,7,9,null,2], low = 3, high = 8

Output: 27

Explanation: Nodes 5, 3, 8, 4 and 7 are in the range [3, 8]. 5 + 3 + 8 + 4 + 7 = 27.

Example 2:

Input: root = [4,3,5,2,null], low = 2, high = 4

Output: 9

Explanation: Nodes 4, 3, and 2 are in the range [2, 4]. 4 + 3 + 2 = 9.

Constraints:

  • 1 <= The number of nodes in the tree <= 20,000.
  • 1 <= Node.val, low, high <= 100,000
  • All Node.val are unique.


Topics

Company Tags

Please upgrade to NeetCode Pro to view company tags.



Prerequisites

Before attempting this problem, you should be comfortable with:

  • Binary Search Tree (BST) Properties - Understanding that left subtree values are smaller and right subtree values are larger than the current node
  • Depth First Search (DFS) - Recursive tree traversal to visit all nodes and accumulate values
  • Tree Pruning - Using BST ordering to skip entire subtrees that cannot contain values in the target range

Intuition

We traverse the entire tree and sum up values that fall within the given range. For each node, we check if its value is between low and high, adding it to our sum if so. We then recursively process both children. This approach visits every node regardless of the BST property.

Algorithm

  1. Base case: if the node is null, return 0.
  2. Check if the current node's value is within [low, high]. If yes, include it in the result.
  3. Recursively compute the range sum for the left subtree.
  4. Recursively compute the range sum for the right subtree.
  5. Return the sum of all contributions.
# 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 rangeSumBST(self, root: Optional[TreeNode], low: int, high: int) -> int:
        if not root:
            return 0

        res = root.val if low <= root.val <= high else 0
        res += self.rangeSumBST(root.left, low, high)
        res += self.rangeSumBST(root.right, low, high)
        return res

Time & Space Complexity

  • Time complexity: O(n)O(n)
  • Space complexity: O(n)O(n) for recursion stack.

2. Depth First Search (Optimal)

Intuition

We can leverage the BST property to prune unnecessary branches. If the current node's value is greater than high, all values in the right subtree are also too large, so we only need to search left. Similarly, if the current value is less than low, we only search right. This eliminates entire subtrees that cannot contribute to the sum.

Algorithm

  1. Base case: if the node is null, return 0.
  2. If the current value exceeds high, skip the right subtree and recurse only on the left.
  3. If the current value is below low, skip the left subtree and recurse only on the right.
  4. Otherwise, the current value is in range. Add it to the sum of both subtree results.
  5. Return the computed sum.
# 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 rangeSumBST(self, root: Optional[TreeNode], low: int, high: int) -> int:
        if not root:
            return 0

        if root.val > high:
            return self.rangeSumBST(root.left, low, high)
        if root.val < low:
            return self.rangeSumBST(root.right, low, high)

        return (
            root.val +
            self.rangeSumBST(root.left, low, high) +
            self.rangeSumBST(root.right, low, high)
        )

Time & Space Complexity

  • Time complexity: O(n)O(n)
  • Space complexity: O(n)O(n) for recursion stack.

3. Iterative DFS

Intuition

The recursive solution can be converted to an iterative one using an explicit stack. We maintain the same pruning logic: only push children onto the stack if they might contain values in range. This avoids function call overhead while preserving the efficiency of the optimal approach.

Algorithm

  1. Initialize a stack with the root node and a result variable set to 0.
  2. While the stack is not empty:
    • Pop a node. If null, continue.
    • If the node's value is in range [low, high], add it to the result.
    • If the node's value is greater than low, push the left child.
    • If the node's value is less than high, push the right child.
  3. Return the accumulated result.
# 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 rangeSumBST(self, root: Optional[TreeNode], low: int, high: int) -> int:
        stack = [root]
        res = 0

        while stack:
            node = stack.pop()
            if not node:
                continue

            if low <= node.val <= high:
                res += node.val
            if node.val > low:
                stack.append(node.left)
            if node.val < high:
                stack.append(node.right)

        return res

Time & Space Complexity

  • Time complexity: O(n)O(n)
  • Space complexity: O(n)O(n)

Common Pitfalls

Not Leveraging BST Property for Pruning

Treating the tree as a regular binary tree and visiting every node wastes time. Since it is a BST, when the current node's value exceeds high, the entire right subtree contains only larger values and can be skipped. Similarly, when the value is below low, the left subtree can be skipped. Failing to prune these branches results in O(n) time even when only a small portion of nodes fall within the range.

Incorrect Range Boundary Checks

Using strict inequalities (< and >) instead of inclusive checks (<= and >=) when determining whether to include the current node's value causes off-by-one errors. The condition should be low <= node.val <= high to include boundary values. Missing boundary values leads to incorrect sums when low or high exactly match node values in the tree.