Kth Smallest Element in a BST
Initialize stack and current pointer
We start with an empty stack and set current to the root node (value 3). The count of visited nodes is zero.
stack = []
current = root
count = 0Push current node (3) onto stack and move left
Current node 3 is pushed onto the stack. We move current pointer to its left child (node 1).
while current:
stack.append(current)
current = current.leftPush current node (1) onto stack and move left
Current node 1 is pushed onto the stack. We move current pointer to its left child, which is null.
while current:
stack.append(current)
current = current.leftPop node (1) from stack and visit it
Current is null, so we pop node 1 from the stack to visit it. Count increments to 1.
current = stack.pop()
count += 1Check if count equals k
Count is 1, which equals k=1. The algorithm returns the current node's value 1 as the kth smallest element.
if count == k:
return current.valReturn the kth smallest element
The algorithm returns 1 as the kth smallest element and terminates.
return current.valAdditional step: Explanation of why traversal stops early
Since k=1, the algorithm stops after visiting the first node in in-order traversal, which is the smallest element.
if count == k:
return current.valHypothetical continuation if k was larger: move to right child
If count was less than k, the algorithm would move current pointer to the right child of the popped node to continue traversal.
current = current.rightHypothetical push of right child (4) onto stack
If traversal continued, current node 4 would be pushed onto the stack and traversal would move left to node 2.
while current:
stack.append(current)
current = current.leftSummary: In-order traversal visits nodes in ascending order
The in-order traversal order for this BST is [1, 2, 3, 4]. The algorithm visits nodes in this order, counting until it reaches k.
from typing import Optional
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def kthSmallest(root: Optional[TreeNode], k: int) -> int:
stack = [] # STEP 1: Initialize empty stack
current = root # STEP 1: Start at root
count = 0 # STEP 1: Initialize count
while current or stack: # STEP 2: Continue while nodes remain
while current: # STEP 3: Push all left children
stack.append(current) # STEP 3: Push current
current = current.left # STEP 3: Move left
current = stack.pop() # STEP 4: Pop from stack
count += 1 # STEP 4: Increment count
if count == k: # STEP 5: Check if kth smallest
return current.val # STEP 5: Return value
current = current.right # STEP 6: Move to right child
# Driver code
if __name__ == '__main__':
root = TreeNode(3)
root.left = TreeNode(1)
root.right = TreeNode(4)
root.left.right = TreeNode(2)
print(kthSmallest(root, 1)) # Output: 1Key Takeaways
This insight is hard to see from code alone because the traversal order and counting are implicit; visualization makes it explicit.
Understanding the stack's role clarifies how iterative traversal mimics recursion.
This early stopping is subtle in code but critical for efficiency, and visualization highlights this decision clearly.
