🧠
Brute Force (Full Inorder Traversal Preprocessing)
💡 This approach exists to build intuition by doing the simplest thing: traverse the entire BST upfront and store the sorted elements. It helps beginners understand the problem before optimizing.
Intuition
Perform a full inorder traversal of the BST to get a sorted list of all elements. Then, iterate over this list to return the next smallest element on each call.
Algorithm
- Traverse the BST inorder and store all node values in a list.
- Maintain an index pointer initialized to -1.
- For next(), increment the pointer and return the element at that index.
- For hasNext(), check if the pointer + 1 is within the list bounds.
💡 The main difficulty is realizing that inorder traversal produces sorted order and that storing all elements upfront is simple but costly.
class BSTIterator:
def __init__(self, root):
self.nodes_sorted = []
self.index = -1
self._inorder(root)
def _inorder(self, root):
if root is None:
return
self._inorder(root.left)
self.nodes_sorted.append(root.val)
self._inorder(root.right)
def next(self):
self.index += 1
return self.nodes_sorted[self.index]
def hasNext(self):
return self.index + 1 < len(self.nodes_sorted)
# Driver code example:
# root = TreeNode(7, TreeNode(3), TreeNode(15, TreeNode(9), TreeNode(20)))
# iterator = BSTIterator(root)
# print(iterator.next()) # 3
# print(iterator.next()) # 7
# print(iterator.hasNext()) # True
# print(iterator.next()) # 9
# print(iterator.hasNext()) # True
# print(iterator.next()) # 15
# print(iterator.hasNext()) # True
# print(iterator.next()) # 20
# print(iterator.hasNext()) # False
Line Notes
self.nodes_sorted = []Initialize list to store all BST elements in sorted order
self.index = -1Start pointer before the first element to prepare for next() calls
self._inorder(root)Perform full inorder traversal to fill nodes_sorted
self.nodes_sorted.append(root.val)Add current node's value to the sorted list
self.index += 1Move pointer forward to get next smallest element
return self.nodes_sorted[self.index]Return the element at the current pointer
return self.index + 1 < len(self.nodes_sorted)Check if more elements remain after current pointer
import java.util.*;
class BSTIterator {
private List<Integer> nodesSorted;
private int index;
public BSTIterator(TreeNode root) {
nodesSorted = new ArrayList<>();
index = -1;
inorder(root);
}
private void inorder(TreeNode root) {
if (root == null) return;
inorder(root.left);
nodesSorted.add(root.val);
inorder(root.right);
}
public int next() {
index++;
return nodesSorted.get(index);
}
public boolean hasNext() {
return index + 1 < nodesSorted.size();
}
// Driver code example:
// public static void main(String[] args) {
// TreeNode root = new TreeNode(7, new TreeNode(3), new TreeNode(15, new TreeNode(9), new TreeNode(20)));
// BSTIterator iterator = new BSTIterator(root);
// System.out.println(iterator.next()); // 3
// System.out.println(iterator.next()); // 7
// System.out.println(iterator.hasNext()); // true
// System.out.println(iterator.next()); // 9
// System.out.println(iterator.hasNext()); // true
// System.out.println(iterator.next()); // 15
// System.out.println(iterator.hasNext()); // true
// System.out.println(iterator.next()); // 20
// System.out.println(iterator.hasNext()); // false
// }
}
class TreeNode {
int val;
TreeNode left, right;
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val; this.left = left; this.right = right;
}
}
Line Notes
nodesSorted = new ArrayList<>();Initialize list to hold sorted BST elements
index = -1;Pointer starts before first element for next()
inorder(root);Fill nodesSorted with inorder traversal
nodesSorted.add(root.val);Add current node's value to sorted list
index++;Advance pointer to next element
return nodesSorted.get(index);Return element at current pointer
return index + 1 < nodesSorted.size();Check if more elements remain
#include <iostream>
#include <vector>
using namespace std;
struct TreeNode {
int val;
TreeNode *left, *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class BSTIterator {
vector<int> nodesSorted;
int index;
void inorder(TreeNode* root) {
if (!root) return;
inorder(root->left);
nodesSorted.push_back(root->val);
inorder(root->right);
}
public:
BSTIterator(TreeNode* root) {
index = -1;
inorder(root);
}
int next() {
index++;
return nodesSorted[index];
}
bool hasNext() {
return index + 1 < (int)nodesSorted.size();
}
};
// Driver code example:
// int main() {
// TreeNode* root = new TreeNode(7);
// root->left = new TreeNode(3);
// root->right = new TreeNode(15);
// root->right->left = new TreeNode(9);
// root->right->right = new TreeNode(20);
// BSTIterator iterator(root);
// cout << iterator.next() << endl; // 3
// cout << iterator.next() << endl; // 7
// cout << iterator.hasNext() << endl; // 1 (true)
// cout << iterator.next() << endl; // 9
// cout << iterator.hasNext() << endl; // 1 (true)
// cout << iterator.next() << endl; // 15
// cout << iterator.hasNext() << endl; // 1 (true)
// cout << iterator.next() << endl; // 20
// cout << iterator.hasNext() << endl; // 0 (false)
// return 0;
// }
Line Notes
vector<int> nodesSorted;Stores all BST elements in sorted order
int index;Pointer to track current position in nodesSorted
inorder(root);Populate nodesSorted with inorder traversal
nodesSorted.push_back(root->val);Add current node's value to vector
index++;Move pointer forward for next element
return nodesSorted[index];Return element at current pointer
return index + 1 < (int)nodesSorted.size();Check if more elements remain
class BSTIterator {
constructor(root) {
this.nodesSorted = [];
this.index = -1;
this._inorder(root);
}
_inorder(root) {
if (!root) return;
this._inorder(root.left);
this.nodesSorted.push(root.val);
this._inorder(root.right);
}
next() {
this.index++;
return this.nodesSorted[this.index];
}
hasNext() {
return this.index + 1 < this.nodesSorted.length;
}
}
// Driver code example:
// const root = { val: 7, left: { val: 3, left: null, right: null }, right: { val: 15, left: { val: 9, left: null, right: null }, right: { val: 20, left: null, right: null } } };
// const iterator = new BSTIterator(root);
// console.log(iterator.next()); // 3
// console.log(iterator.next()); // 7
// console.log(iterator.hasNext()); // true
// console.log(iterator.next()); // 9
// console.log(iterator.hasNext()); // true
// console.log(iterator.next()); // 15
// console.log(iterator.hasNext()); // true
// console.log(iterator.next()); // 20
// console.log(iterator.hasNext()); // false
Line Notes
this.nodesSorted = []Initialize array to hold sorted BST elements
this.index = -1Pointer starts before first element for next()
this._inorder(root)Fill nodesSorted with inorder traversal
this.nodesSorted.push(root.val)Add current node's value to array
this.index++Advance pointer to next element
return this.nodesSorted[this.index]Return element at current pointer
return this.index + 1 < this.nodesSorted.lengthCheck if more elements remain
TimeO(n) preprocessing, O(1) per next()/hasNext() call
SpaceO(n) to store all nodes in a list
We traverse all nodes once to build the list, then each next/hasNext is just pointer arithmetic.
💡 For n=100,000 nodes, this means 100,000 operations upfront, then constant time per call.
Interview Verdict: Accepted but inefficient for large trees due to O(n) space
This approach is easy to implement but uses too much memory and is not optimal for large inputs.