BST Delete Operation in DSA Python - Time & Space Complexity
We want to understand how the time to delete a node from a Binary Search Tree (BST) changes as the tree grows.
How does the number of steps needed to find and remove a node grow with the size of the tree?
Analyze the time complexity of the following BST delete function.
def delete_node(root, key):
def find_min(node):
while node.left:
node = node.left
return node
if not root:
return root
if key < root.val:
root.left = delete_node(root.left, key)
elif key > root.val:
root.right = delete_node(root.right, key)
else:
if not root.left:
return root.right
elif not root.right:
return root.left
temp = find_min(root.right)
root.val = temp.val
root.right = delete_node(root.right, temp.val)
return root
This code finds the node with the given key, removes it, and adjusts the tree to keep BST rules.
Look for loops and recursive calls that repeat work.
- Primary operation: Recursively searching down the tree to find the node to delete.
- How many times: At most once per level of the tree, from root to leaf.
- Additional operation: Finding the minimum node in the right subtree, which is a simple loop down the left children.
As the tree grows, the number of levels increases, so the steps to find or adjust nodes grow with the tree height.
| Input Size (n) | Approx. Operations (steps down tree) |
|---|---|
| 10 | About 3 to 4 steps |
| 100 | About 6 to 7 steps |
| 1000 | About 9 to 10 steps |
Pattern observation: The number of steps grows roughly with the height of the tree, which is about log base 2 of n if the tree is balanced.
Time Complexity: O(h) where h is the height of the BST
This means the time to delete depends on how tall the tree is, not just how many nodes it has.
[X] Wrong: "Deleting a node always takes the same time regardless of tree shape."
[OK] Correct: If the tree is very unbalanced (like a linked list), the height can be as big as the number of nodes, making deletion slower.
Understanding how tree height affects delete operation time helps you explain trade-offs in data structures and shows you can analyze real code performance.
"What if the BST is always perfectly balanced? How would that change the time complexity of delete?"
Practice
Solution
Step 1: Understand leaf node deletion
A leaf node has no children, so removing it does not affect other nodes.Step 2: Effect on BST structure
Since no children exist, simply remove the node and update its parent's pointer to null.Final Answer:
The node is simply removed without affecting other nodes. -> Option CQuick Check:
Leaf node deletion = simple removal [OK]
- Thinking children need rearrangement
- Assuming root always changes
- Believing tree rebuild is needed
Solution
Step 1: Identify required parameters
To delete a node, we need the BST root and the key to delete.Step 2: Check function signature
Only def deleteNode(root, key): has both parameters in correct order.Final Answer:
def deleteNode(root, key): -> Option BQuick Check:
Function needs root and key [OK]
- Swapping parameter order
- Missing one parameter
- Using only key or root alone
15
/ \
10 20
/ \ \
8 12 25
Solution
Step 1: Delete node 10 with two children
Node 10 has two children (8 and 12). Replace it with its inorder successor (12).Step 2: Adjust tree and perform inorder traversal
After replacement, node 12 replaces 10, and 12's original position is removed. Inorder traversal is [8, 12, 15, 20, 25].Final Answer:
[8, 12, 15, 20, 25] -> Option DQuick Check:
Inorder after delete = [8, 12, 15, 20, 25] [OK]
- Not replacing node with successor
- Leaving deleted node in traversal
- Incorrect traversal order
def deleteNode(root, key):
if not root:
return root
if key < root.val:
deleteNode(root.left, key)
elif key > root.val:
deleteNode(root.right, key)
else:
if not root.left:
return root.right
elif not root.right:
return root.left
temp = findMin(root.right)
root.val = temp.val
deleteNode(root.right, temp.val)
return root
Solution
Step 1: Check recursive calls for updating children
Recursive calls like deleteNode(root.left, key) do not assign the result back to root.left, so changes are lost.Step 2: Correct by assigning returned subtree
We must write root.left = deleteNode(root.left, key) and root.right = deleteNode(root.right, key) to update pointers properly.Final Answer:
Recursive calls do not update root's children pointers. -> Option AQuick Check:
Update children with recursive call results [OK]
- Ignoring returned subtree after recursion
- Assuming in-place changes without assignment
- Missing base case (not the main issue here)
Solution
Step 1: Understand deletion of node with two children
Direct removal breaks BST rules; we must replace the node with a suitable value.Step 2: Use inorder predecessor or successor
Replacing with inorder predecessor (max in left subtree) or successor (min in right subtree) keeps BST order intact.Step 3: Delete the replaced node recursively
After replacement, delete the predecessor/successor node which will have at most one child.Final Answer:
Replace the node with its inorder predecessor or successor, then delete that node. -> Option AQuick Check:
Use inorder predecessor/successor for two-child deletion [OK]
- Replacing with only left or right child
- Removing node without replacement
- Breaking BST ordering rules
Ready to prove it?
Pass the test and this pattern moves unknown
