701. Insert into a Binary Search Tree - Explanation
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.valare unique. - It's guaranteed that
valdoes not exist in the original BST.
Topics
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
- If
rootisnull, create and return a new node with the given value. - If
valis greater thanroot.val, recursively insert into the right subtree and updateroot.rightwith the result. - Otherwise, recursively insert into the left subtree and update
root.leftwith the result. - Return the root (unchanged if not
null, or the new node if it wasnull).
# 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 rootTime & Space Complexity
- Time complexity:
- Space complexity: for the recursion stack.
Where 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
- If
rootisnull, return a new node with the given value. - Start with
curpointing to the root. - Loop indefinitely:
- If
valis greater thancur.val, check ifcur.rightisnull. If so, insert the new node there and return the root. Otherwise, movecurtocur.right. - If
valis less than or equal tocur.val, check ifcur.leftisnull. If so, insert the new node there and return the root. Otherwise, movecurtocur.left.
- If
# 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.leftTime & Space Complexity
- Time complexity:
- Space complexity: extra space.
Where 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.
Sign in to join the discussion