Forgetting null/base-case handling
Wrong move: Recursive traversal assumes children always exist.
Usually fails on: Leaf nodes throw errors or create wrong depth/path values.
Fix: Handle null/base cases before recursive transitions.
Build confidence with an intuition-first walkthrough focused on tree fundamentals.
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 = [10,5,15,3,7,null,18], low = 7, high = 15 Output: 32 Explanation: Nodes 7, 10, and 15 are in the range [7, 15]. 7 + 10 + 15 = 32.
Example 2:
Input: root = [10,5,15,3,7,13,18,1,null,6], low = 6, high = 10 Output: 23 Explanation: Nodes 6, 7, and 10 are in the range [6, 10]. 6 + 7 + 10 = 23.
Constraints:
[1, 2 * 104].1 <= Node.val <= 1051 <= low <= high <= 105Node.val are unique.Problem summary: 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].
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Tree
[10,5,15,3,7,null,18] 7 15
[10,5,15,3,7,13,18,1,null,6] 6 10
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #938: Range Sum of BST
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int rangeSumBST(TreeNode root, int low, int high) {
return dfs(root, low, high);
}
private int dfs(TreeNode root, int low, int high) {
if (root == null) {
return 0;
}
int x = root.val;
int ans = low <= x && x <= high ? x : 0;
if (x > low) {
ans += dfs(root.left, low, high);
}
if (x < high) {
ans += dfs(root.right, low, high);
}
return ans;
}
}
// Accepted solution for LeetCode #938: Range Sum of BST
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func rangeSumBST(root *TreeNode, low int, high int) int {
var dfs func(*TreeNode) int
dfs = func(root *TreeNode) (ans int) {
if root == nil {
return 0
}
x := root.Val
if low <= x && x <= high {
ans += x
}
if x > low {
ans += dfs(root.Left)
}
if x < high {
ans += dfs(root.Right)
}
return
}
return dfs(root)
}
# Accepted solution for LeetCode #938: Range Sum of BST
# 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:
def dfs(root: Optional[TreeNode]) -> int:
if root is None:
return 0
x = root.val
ans = x if low <= x <= high else 0
if x > low:
ans += dfs(root.left)
if x < high:
ans += dfs(root.right)
return ans
return dfs(root)
// Accepted solution for LeetCode #938: Range Sum of BST
struct Solution;
use rustgym_util::*;
trait Preorder {
fn preorder(&self, l: i32, r: i32, sum: &mut i32);
}
impl Preorder for TreeLink {
fn preorder(&self, l: i32, r: i32, sum: &mut i32) {
if let Some(node) = self {
let node = node.borrow();
let left = &node.left;
let right = &node.right;
let val = node.val;
if val >= l && val <= r {
*sum += val;
}
if val > l {
left.preorder(l, r, sum)
}
if val < r {
right.preorder(l, r, sum);
}
}
}
}
impl Solution {
fn range_sum_bst(root: TreeLink, l: i32, r: i32) -> i32 {
let mut sum = 0;
root.preorder(l, r, &mut sum);
sum
}
}
#[test]
fn test() {
let root = tree!(10, tree!(5, tree!(3), tree!(7)), tree!(15, None, tree!(18)));
assert_eq!(Solution::range_sum_bst(root, 7, 15), 32);
}
// Accepted solution for LeetCode #938: Range Sum of BST
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/
function rangeSumBST(root: TreeNode | null, low: number, high: number): number {
const dfs = (root: TreeNode | null): number => {
if (!root) {
return 0;
}
const { val, left, right } = root;
let ans = low <= val && val <= high ? val : 0;
if (val > low) {
ans += dfs(left);
}
if (val < high) {
ans += dfs(right);
}
return ans;
};
return dfs(root);
}
Use this to step through a reusable interview workflow for this problem.
BFS with a queue visits every node exactly once — O(n) time. The queue may hold an entire level of the tree, which for a complete binary tree is up to n/2 nodes = O(n) space. This is optimal in time but costly in space for wide trees.
Every node is visited exactly once, giving O(n) time. Space depends on tree shape: O(h) for recursive DFS (stack depth = height h), or O(w) for BFS (queue width = widest level). For balanced trees h = log n; for skewed trees h = n.
Review these before coding to avoid predictable interview regressions.
Wrong move: Recursive traversal assumes children always exist.
Usually fails on: Leaf nodes throw errors or create wrong depth/path values.
Fix: Handle null/base cases before recursive transitions.