BST Inorder Successor in DSA Python - Time & Space Complexity
We want to understand how long it takes to find the next bigger value in a Binary Search Tree (BST).
How does the time grow as the tree gets bigger?
Analyze the time complexity of the following code snippet.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def inorder_successor(root, p):
successor = None
while root:
if p.val < root.val:
successor = root
root = root.left
else:
root = root.right
return successor
This code finds the inorder successor of a node p in a BST by walking down from the root.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that moves down the tree nodes.
- How many times: At most once per level of the tree, from root to leaf.
Each step moves one level down the tree, so the number of steps depends on the tree height.
| Input Size (n) | Approx. Operations (steps down tree) |
|---|---|
| 10 | Up to 4 (if tree is balanced) |
| 100 | Up to 7 |
| 1000 | Up to 10 |
Pattern observation: The steps grow slowly, roughly with the height of the tree, not the total nodes.
Time Complexity: O(h)
This means the time depends on the height of the tree, which is the number of levels from root to leaf.
[X] Wrong: "Finding the inorder successor always takes O(n) time because we might visit all nodes."
[OK] Correct: We only move down one path from root to leaf, not all nodes, so the time depends on tree height, not total nodes.
Understanding how tree height affects search time helps you explain why balanced trees are faster and why this method is efficient.
"What if the BST is not balanced but skewed like a linked list? How would the time complexity change?"
Practice
Solution
Step 1: Understand inorder traversal order
Inorder traversal visits nodes in ascending order of their keys in a BST.Step 2: Define inorder successor
The inorder successor of a node is the next node visited after it in inorder traversal, which is the smallest node greater than the given node.Final Answer:
The node with the smallest key greater than the given node's key -> Option CQuick Check:
Inorder successor = next larger node [OK]
- Confusing successor with predecessor
- Thinking successor is always right child
- Assuming successor is parent node
Solution
Step 1: Identify parameters needed
To find inorder successor, we need the BST root and the target node p.Step 2: Check function signature correctness
def inorder_successor(self, root: 'Node', p: 'Node') -> 'Node': includes self (method), root, and p with type hints, matching common BST method style.Final Answer:
def inorder_successor(self, root: 'Node', p: 'Node') -> 'Node': -> Option BQuick Check:
Correct parameters and type hints [OK]
- Missing root parameter
- Omitting type hints in modern Python
- Wrong parameter order or missing self
20
/ \
10 30
\ \
15 40
Solution
Step 1: Locate node 15 and find its right subtree
Node 15 has no right child, so successor is one of its ancestors.Step 2: Find the lowest ancestor whose left child is also ancestor of 15
Node 20 is the parent of 15's ancestor and 15 is in left subtree of 20, so successor is 20.Final Answer:
20 -> Option DQuick Check:
Next bigger after 15 is 20 [OK]
- Choosing right child when none exists
- Picking 30 or 40 which are too large
- Confusing predecessor with successor
def inorder_successor(root, p):
if p.right:
curr = p.right
while curr.left:
curr = curr.left
return curr
else:
curr = root
successor = None
while curr:
if p.val < curr.val:
successor = curr
curr = curr.left
else:
curr = curr.right
return NoneSolution
Step 1: Analyze return statements
When p has no right child, function finds successor but returns None instead of successor.Step 2: Identify missing return of successor
At the end of else block, it should return successor, not None.Final Answer:
The function returns None instead of successor at the end -> Option AQuick Check:
Return successor, not None [OK]
- Returning None instead of found successor
- Not updating successor inside loop
- Ignoring right subtree case
Solution
Step 1: Check if node has right child
If yes, successor is the leftmost node in right subtree.Step 2: If no right child, move up using parent pointer
Go up until current node is left child of its parent; that parent is successor.Final Answer:
If node has right child, successor is leftmost node in right subtree; else go up until node is left child of its parent -> Option AQuick Check:
Use right subtree or climb parents [OK]
- Confusing left and right child cases
- Assuming successor is always parent
- Not using parent pointer to climb up
Ready to prove it?
Pass the test and this pattern moves unknown
