THN Interview Prep

173. Binary Search Tree Iterator

Quick Identifier

  • Topic: trees
  • Pattern: Iterative inorder (stack)
  • Difficulty: Medium
  • Companies: Amazon, Facebook, Google, Microsoft, Bloomberg
  • Frequency: High
  • LeetCode: 173

Quick Sights

  • Time Complexity: O(h) from the optimal approach.
  • Space Complexity: O(1) from the optimal approach.
  • Core Mechanism: Design an iterator over a BST starting from the smallest element: constructor stores the root; next() returns the next smallest value in ascending order; hasNext() tells whether more exist. Both amortized O(1) time are expected.

Concept Explanation

Design an iterator over a BST starting from the smallest element: constructor stores the root; next() returns the next smallest value in ascending order; hasNext() tells whether more exist. Both amortized O(1) time are expected.

State the invariant before coding: what partial result is already correct, what work remains, and what value or state each recursive/iterative step must preserve.

Recognition cues:

  • Controlled inorder traversal without materializing full list up front
  • Stack holds the left spine; popping visits node; then push left spine of right child
  • Same machinery as 230 kth smallest stopped incrementally

Study Pattern (SDE3+)

  • 0-3 min: restate I/O and brittle edges aloud, then verbalize two approaches with time/space before you touch the keyboard.
  • Implementation pass: one-line invariant above the tight loop; state what progress you make each iteration.
  • 5 min extension: pick one constraint twist (immutable input, stream, bounded memory, parallel readers) and explain what in your solution breaks without a refactor.

Diagram

This diagram shows the algorithm movement for this problem family.

Loading diagram…

Approaches

  • Brute force — inorder into array, index pointer — O(n) memory upfront.
  • Optimal — lazy stack inorder — O(h) stack, amortized O(1) per next() across full traversal.

Optimal Solution

Go

package main

type TreeNode struct {
	Val   int
	Left  *TreeNode
	Right *TreeNode
}

type BSTIterator struct {
	stack []*TreeNode
}

func Constructor(root *TreeNode) BSTIterator {
	iter := BSTIterator{stack: []*TreeNode{}}
	iter.pushLeftBranch(root)
	return iter
}

func (iter *BSTIterator) pushLeftBranch(node *TreeNode) {
	for node != nil {
		iter.stack = append(iter.stack, node)
		node = node.Left
	}
}

func (iter *BSTIterator) Next() int {
	last := len(iter.stack) - 1
	node := iter.stack[last]
	iter.stack = iter.stack[:last]
	iter.pushLeftBranch(node.Right)
	return node.Val
}

func (iter *BSTIterator) HasNext() bool {
	return len(iter.stack) > 0
}

JavaScript

class TreeNode {
	constructor(val = 0, left = null, right = null) {
		this.val = val;
		this.left = left;
		this.right = right;
	}
}

class BSTIterator {
	constructor(root) {
		this.stack = [];
		this.pushLeftBranch(root);
	}

	pushLeftBranch(node) {
		while (node !== null) {
			this.stack.push(node);
			node = node.left;
		}
	}

	next() {
		const node = this.stack.pop();
		this.pushLeftBranch(node.right);
		return node.val;
	}

	hasNext() {
		return this.stack.length > 0;
	}
}

Walkthrough

BST 7 / 3,15 / null,null,9,20. Iterator fills stack along left from root: [7,3].

callpoppush right branchnext value
next3nothing3
next7push 15 spine → [15,9]7
ascending order

Invariant: stack always holds unvisited nodes whose predecessors are done; in BST this yields sorted next().

Edge Cases

  • Empty tree → hasNext false immediately
  • Right-skewed tree → stack depth O(n) worst

Pitfalls

  • Pushing entire right subtree eagerly instead of only left spine of right child
  • Naming clash with Go Constructor — LeetCode uses this name literally

Similar Problems

Variants

  • Bidirectional iterator (prev) — mirror stack on right spines.
  • k smallest streaming resets — combine with size-balanced ideas.

Mind-Map Tags

#trees #bst #iterator #stack #lazy-inorder

Mark this page when you finish learning it.

Last updated on

Spotted something unclear or wrong on this page?

On this page