701. Insert into a Binary Search Tree - Explanation

Problem Link

Description

You are given the root node of a binary search tree (BST) and a value val to insert into the tree. Return the root node of the BST after the insertion. It is guaranteed that the new value does not exist in the original BST.

Note: There may exist multiple valid ways for the insertion, as long as the tree remains a BST after insertion. You can return any of them.

Example 1:

Input: root = [5,3,9,1,4], val = 6

Output: [5,3,9,1,4,6]

Example 2:

Input: root = [5,3,6,null,4,null,10,null,null,7], val = 9

Output: [5,3,6,null,4,null,10,null,null,7,null,null,9]

Constraints:

  • 0 <= The number of nodes in the tree <= 10,000.
  • -100,000,000 <= val, Node.val <= 100,000,000
  • All the values Node.val are unique.
  • It's guaranteed that val does not exist in the original BST.


Topics

Company Tags

Please upgrade to NeetCode Pro to view company tags.



Prerequisites

Before attempting this problem, you should be comfortable with:

  • Binary Search Trees - Understanding the BST property where left subtree values are smaller and right subtree values are larger
  • Tree Traversal - Navigating through a tree by comparing values to decide left or right direction
  • Recursion - Using recursive calls to traverse down the tree and link new nodes back to parents

1. Recursion

Intuition

In a BST, every node's left subtree contains only values smaller than the node, and the right subtree contains only values larger. This property tells us exactly where to go when inserting: compare the value with the current node and recurse left or right accordingly.
We keep traversing until we hit a null position, which is exactly where the new node belongs. The recursion naturally handles this by returning a new node when we reach an empty spot.
The beauty of this approach is that we don't need to track parent nodes explicitly; the recursive call stack handles the linking automatically.

Algorithm

  1. If root is null, create and return a new node with the given value.
  2. If val is greater than root.val, recursively insert into the right subtree and update root.right with the result.
  3. Otherwise, recursively insert into the left subtree and update root.left with the result.
  4. Return the root (unchanged if not null, or the new node if it was null).
# 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 insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if not root:
            return TreeNode(val)

        if val > root.val:
            root.right = self.insertIntoBST(root.right, val)
        else:
            root.left = self.insertIntoBST(root.left, val)

        return root

Time & Space Complexity

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

Where hh is the height of the given binary search tree.


2. Iteration

Intuition

The iterative approach follows the same logic as recursion but uses a loop instead of the call stack. We traverse down the tree, comparing values at each node to decide which direction to go.
When we find a null child in the direction we need to go, we've found the insertion point. We create the new node and attach it directly.
This approach uses O(1) extra space since we don't need the recursion stack, making it more memory-efficient for deep trees.

Algorithm

  1. If root is null, return a new node with the given value.
  2. Start with cur pointing to the root.
  3. Loop indefinitely:
    • If val is greater than cur.val, check if cur.right is null. If so, insert the new node there and return the root. Otherwise, move cur to cur.right.
    • If val is less than or equal to cur.val, check if cur.left is null. If so, insert the new node there and return the root. Otherwise, move cur to cur.left.
# 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 insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if not root:
            return TreeNode(val)

        cur = root
        while True:
            if val > cur.val:
                if not cur.right:
                    cur.right = TreeNode(val)
                    return root
                cur = cur.right
            else:
                if not cur.left:
                    cur.left = TreeNode(val)
                    return root
                cur = cur.left

Time & Space Complexity

  • Time complexity: O(h)O(h)
  • Space complexity: O(1)O(1) extra space.

Where hh is the height of the given binary search tree.


Common Pitfalls

Forgetting to Return the New Node for Empty Trees

When the tree is empty (root is null), failing to create and return a new node with the given value results in returning null instead of the single-node tree. The base case must explicitly handle this by returning new TreeNode(val).

Not Linking the New Node Back to the Parent

In the iterative approach, inserting the new node without properly linking it to the parent's left or right pointer means the node is created but never connected to the tree. The new node must be assigned to either cur.left or cur.right based on the comparison.

Incorrect Comparison Direction

Comparing values with the wrong inequality operator (e.g., using < instead of >) causes nodes to be inserted on the wrong side of the tree, violating the BST property. Values greater than the current node must go right, and values less than or equal must go left.