Taro Logo

Insert into a Binary Search Tree

Medium
Amazon logo
Amazon
2 views
Topics:
TreesRecursion

You are given the root node of a binary search tree (BST) and a value 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.

Notice that 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:

Given the following BST and value:

root = [4,2,7,1,3]
val = 5

Insert val into the BST. One possible result is:

[4,2,7,1,3,5]

Example 2:

Given the following BST and value:

root = [40,20,60,10,30,50,70]
val = 25

Insert val into the BST. One possible result is:

[40,20,60,10,30,50,70,null,null,25]

Write a function that takes the root of a BST and an integer value as input and returns the root of the BST after inserting the value such that the BST properties are maintained.

Solution


Naive Solution

A brute force approach to inserting a value into a Binary Search Tree (BST) would involve traversing the tree to find the appropriate location to insert the new node while maintaining the BST properties. This might involve checking each node and comparing the value to be inserted with the node's value.

Algorithm

  1. If the tree is empty, create a new node with the given value and return it as the new root.
  2. If the tree is not empty, start from the root.
  3. Compare the value to be inserted with the current node's value.
  4. If the value is less than the current node's value, move to the left child. If the left child is null, insert the new node as the left child.
  5. If the value is greater than the current node's value, move to the right child. If the right child is null, insert the new node as the right child.
  6. Repeat steps 3-5 until the correct position is found.

Code (Java)

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int val) {
        this.val = val;
    }
}

public class InsertIntoBST {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        if (root == null) {
            return new TreeNode(val);
        }

        TreeNode current = root;
        while (true) {
            if (val < current.val) {
                if (current.left == null) {
                    current.left = new TreeNode(val);
                    break;
                } else {
                    current = current.left;
                }
            } else {
                if (current.right == null) {
                    current.right = new TreeNode(val);
                    break;
                } else {
                    current = current.right;
                }
            }
        }
        return root;
    }
}

Time and Space Complexity

  • Time Complexity: O(h), where h is the height of the tree. In the worst case (skewed tree), h can be equal to n (number of nodes), making it O(n). In the average case (balanced tree), it's O(log n).
  • Space Complexity: O(1), as it is an iterative approach and uses a constant amount of extra space.

Optimal Solution

The optimal solution involves the same basic idea but can be expressed more concisely using recursion. The BST properties are still maintained during the insertion process.

Algorithm

  1. If the current node is null, create a new node with the given value and return it.
  2. If the value is less than the current node's value, recursively call the function on the left subtree and update the left child of the current node with the returned result.
  3. If the value is greater than the current node's value, recursively call the function on the right subtree and update the right child of the current node with the returned result.
  4. Return the current node.

Code (Java)

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int val) {
        this.val = val;
    }
}

public class InsertIntoBST {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        if (root == null) {
            return new TreeNode(val);
        }
        
        if (val < root.val) {
            root.left = insertIntoBST(root.left, val);
        } else {
            root.right = insertIntoBST(root.right, val);
        }
        
        return root;
    }
}

Time and Space Complexity

  • Time Complexity: O(h), where h is the height of the tree. In the worst case (skewed tree), h can be equal to n (number of nodes), making it O(n). In the average case (balanced tree), it's O(log n).
  • Space Complexity: O(h) due to the recursive call stack. In the worst case, it can be O(n), and in the average case (balanced tree), it's O(log n).

Edge Cases

  • Empty Tree: If the root is null, the function should create a new node and return it.
  • Inserting at Leaf Node: If the value needs to be inserted as a leaf node (either as the left or right child of a node), the function should correctly attach the new node.
  • Large or Small Values: The value to be inserted can be very large or very small compared to the existing values in the tree. The algorithm should still correctly insert the node.