Skip to main content

How to Search for a Node in a Binary Search Tree (BST) – Efficient Solutions Explained

When working with Binary Search Trees (BSTs), one of the most common operations is searching for a node with a specific value. This operation is fundamental to many algorithms and data structures that rely on trees. In this blog post, we will explore how to search for a node in a Binary Search Tree (BST), explain the step-by-step approach, and optimize it for better performance.

What is a Binary Search Tree (BST)?

Before diving into the search algorithm, let's quickly define a Binary Search Tree (BST). A BST is a type of binary tree where each node has at most two children: a left child and a right child. The key property of a BST is that for each node:

  • All values in the left subtree are less than or equal to the node’s value.
  • All values in the right subtree are greater than or equal to the node’s value.

This property allows for efficient searching, as we can eliminate half of the remaining search space at each step, just like binary search in an array.


The Problem: Search in a Binary Search Tree (LeetCode Problem 700)

Problem Statement:

Given the root of a Binary Search Tree and a value val, we need to find the node in the BST where the node's value equals val. If such a node exists, return the subtree rooted at that node. If the node is not found, return NULL.


Solution Overview

The key to solving this problem efficiently lies in the properties of the Binary Search Tree (BST). Since the tree is sorted, the search for any value val can be done in O(h) time, where h is the height of the tree.

We have two main approaches to solve this problem:

  1. Recursive Approach
  2. Iterative Approach

Let's break down both approaches and see how they work.


1. Recursive Approach

The recursive approach leverages the structure of the BST to search for the desired value. We start at the root of the tree and check whether the value is equal to the current node’s value. Based on the value comparison, we move either left or right.

Step-by-Step Explanation:

  1. If the root is NULL, the tree is empty, and the value is not found. Return NULL.
  2. If the value at the current node matches the target value, return the node.
  3. If the target value is smaller than the current node’s value, recursively search the left subtree.
  4. If the target value is larger, recursively search the right subtree.

This recursive approach works because, at each node, we either search the left or right subtree based on the BST property.

Recursive Code Example:

class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val)
    {
        // Base case: If the node is NULL or the value matches the current node's value
        if (!root || root->val == val)
        {
            return root;
        }

        // If the target value is smaller, search in the left subtree
        if (val < root->val)
        {
            return searchBST(root->left, val);
        }

        // If the target value is larger, search in the right subtree
        return searchBST(root->right, val);
    }
};

Time Complexity: O(h), where h is the height of the tree. In the worst case (unbalanced tree), the time complexity could be O(n), where n is the number of nodes.

Space Complexity: O(h), where h is the height of the tree. This is due to the recursive stack. In the worst case of an unbalanced tree, the space complexity could be O(n).


2. Iterative Approach

The iterative approach eliminates recursion and uses a loop to traverse the tree. We can search for the target value in a similar manner to the recursive approach but without the overhead of recursive function calls.

Step-by-Step Explanation:

  1. Start at the root node.
  2. While the current node is not NULL, compare the target value with the node’s value.
  3. If the value is found, return the current node.
  4. If the target value is smaller than the current node’s value, move to the left child.
  5. If the target value is larger, move to the right child.
  6. If you reach a NULL node, return NULL, indicating the value does not exist in the tree.

Iterative Code Example:

class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        while (root != NULL) {
            if (root->val == val) {
                return root;
            }
            // Move to the left or right subtree based on the value
            root = (val < root->val) ? root->left : root->right;
        }
        return NULL;  // If the value was not found
    }
};

Time Complexity: O(h), where h is the height of the tree. Similar to the recursive approach, the time complexity can be O(n) in the worst case for an unbalanced tree.

Space Complexity: O(1). Since we’re not using the recursion stack, the space complexity is constant, making this approach more space-efficient.


Which Approach Should You Use?

Both approaches (recursive and iterative) solve the problem effectively, but they come with different trade-offs:

  • Recursive Approach: Easier to understand and write, but the recursion stack can consume extra space in deep trees (unbalanced trees).
  • Iterative Approach: More space-efficient because it avoids recursion, but the code might be slightly less intuitive.

In practice, the iterative approach is often preferred when dealing with very deep trees (to avoid stack overflow issues) or when minimizing space usage is critical.


Optimizing for Balanced Trees

In a balanced Binary Search Tree (BST), the height h is logarithmic relative to the number of nodes (h = O(log n)). In such cases, both time and space complexities for both the recursive and iterative approaches are O(log n), which is highly efficient.

However, if the tree is unbalanced, the height h can become linear in the number of nodes (h = O(n)), and both approaches could degrade to O(n) time and space complexity.

To optimize the search in unbalanced trees, consider using self-balancing trees (such as AVL trees or Red-Black trees) that guarantee logarithmic height.

In this blog post, we explored how to search for a node in a Binary Search Tree (BST). We looked at two approaches: the recursive approach and the iterative approach. Both have their advantages and trade-offs in terms of time and space complexity.

  • Recursive Approach: More intuitive and easier to implement but uses the recursion stack.
  • Iterative Approach: More space-efficient and avoids the recursion stack but might be slightly less intuitive.

Depending on your needs (space efficiency or simplicity), you can choose the appropriate approach. For trees with a lot of nodes or deep structures, the iterative approach might be a better choice.


SEO Tags:

  • Search in Binary Search Tree (BST)
  • Binary Search Tree search algorithm
  • Leetcode 700 search in BST
  • Recursive vs Iterative BST search
  • Optimizing search in BST
  • Binary Tree search
  • Leetcode solution for BST search

Popular posts from this blog

Top 10 Beginner-Friendly LeetCode Questions and Their Solutions

If you're new to solving coding problems on LeetCode, it can feel overwhelming. Where do you start? Which problems are suitable for beginners? Don’t worry! In this blog post, I’ll guide you through 10 beginner-friendly LeetCode questions that are perfect for getting started on your coding journey. These problems will help you build confidence, improve your problem-solving skills, and lay a solid foundation in data structures and algorithms. Why Start with Beginner-Friendly Problems? Before diving into advanced topics like dynamic programming or graph theory, it’s essential to: Build a strong foundation in basic programming concepts. Understand how to approach a coding problem methodically. Gain familiarity with LeetCode’s platform and its problem structure. The following problems are simple yet impactful, designed to introduce you to common techniques like loops, arrays, strings, and basic math operations. 10 Beginner-Friendly LeetCode Problems 1. Two Sum (Easy) Problem Link : Two...

LeetCode 2583: Kth Largest Sum in a Binary Tree – Solution Explained

When working with binary trees, one common task is to analyze the properties of the tree's levels. In this blog post, we'll walk through a solution to LeetCode Problem 2583: Kth Largest Sum in a Binary Tree , a problem that challenges us to compute and find specific sums from different levels of a binary tree. Problem Statement You are given the root of a binary tree and a positive integer k . Your goal is to return the k-th largest level sum in the tree. The level sum is defined as the sum of the values of all nodes at the same depth in the tree. If the number of levels in the tree is less than k , the function should return -1 . Example 1: Input: root = [5, 8, 9, 2, 1, 3, 7, 4, 6] , k = 2 Output: 13 Explanation: Level 1 sum: 5 Level 2 sum: 8 + 9 = 17 Level 3 sum: 2 + 1 + 3 + 7 = 13 Level 4 sum: 4 + 6 = 10 The 2nd largest sum is 13 . Example 2: Input: root = [1, 2, null, 3] , k = 1 Output: 3 Explanation: The largest level sum is 3 (at the third level). This problem essentia...

LeetCode 3370: Smallest Number With All Set Bits – Problem Explanation and Solutions

Are you looking to master bit manipulation and tackle interesting coding challenges? In this post, we’ll explore LeetCode Problem 3370: Smallest Number With All Set Bits . We’ll dive deep into the problem statement, break down a brute force approach, and finally discuss an optimized solution. If you’re preparing for technical interviews or just love solving algorithmic problems, this guide is for you! Problem Statement: Smallest Number With All Set Bits You are given a positive integer n . Your task is to find the smallest number x such that: x is greater than or equal to n . The binary representation of x consists only of set bits ( 1 s). Examples: Example 1: Input: n = 5 Output: 7 Explanation: The binary representation of 7 is 111 , which is the smallest number greater than or equal to 5 with all bits set. Example 2: Input: n = 10 Output: 15 Explanation: The binary representation of 15 is 1111 . Example 3: Input: n = 3 Output: 3 Explanation: The binary representation of 3 is...