
Problem Statement
The BSTIterator class is designed to provide a controlled way of iterating through a binary search tree (BST) using its in-order traversal. The features of the class include:
- Initialization of the iterator with the root of the BST.
- Moving the internal pointer to simulate steps through the traversal, both forward and backwards.
- Checking the availability of next and previous nodes relative to the current position of the pointer.
Key functionalities:
- Initialization (
BSTIterator(TreeNode root)): Constructs an instance with the given tree's root. Internally, it might store the elements in a way that supports efficient in-order traversal from the smallest to largest element. - Check Next (
boolean hasNext()): Determines if there are nodes ahead in the traversal sequence, returningtrueorfalse. - Next Element (
int next()): Moves to the next element in the in-order sequence and returns its value. - Check Previous (
boolean hasPrev()): Checks whether elements are available before the current pointer in the traversal sequence. - Previous Element (
int prev()): Moves to the previous element in the sequence, returning its value.
The BSTIterator initiates its pointer at a virtual position before the smallest element, ensuring that the first next() invocation will correctly return the smallest element in the tree.
Examples
Example 1
Input:
["BSTIterator", "next", "next", "prev", "next", "hasNext", "next", "next", "next", "hasNext", "hasPrev", "prev", "prev"] [[[7, 3, 15, null, null, 9, 20]], [], [], [], [], [], [], [], [], [], [], [], []]
Output:
[null, 3, 7, 3, 7, true, 9, 15, 20, false, true, 15, 9]
Explanation:
Let the BST in-order sequence be [3, 7, 9, 15, 20].
BSTIterator bSTIterator = new BSTIterator([7, 3, 15, null, null, 9, 20]);
Initializes the iterator.bSTIterator.next();➜ returns3bSTIterator.next();➜ returns7bSTIterator.prev();➜ returns3bSTIterator.next();➜ returns7bSTIterator.hasNext();➜ returnstruebSTIterator.next();➜ returns9bSTIterator.next();➜ returns15bSTIterator.next();➜ returns20bSTIterator.hasNext();➜ returnsfalsebSTIterator.hasPrev();➜ returnstruebSTIterator.prev();➜ returns15bSTIterator.prev();➜ returns9
Constraints
- The number of nodes in the tree is in the range
[1, 105]. 0 <= Node.val <= 106- At most
105calls will be made tohasNext,next,hasPrev, andprev.
Approach and Intuition
The problem revolves around simulating an in-order traversal on a BST using an iterator with additional capabilities like checking for next and previous elements and moving the pointer accordingly.
Key Concepts in Play:
- In-order Traversal: This type of traversal ensures that the tree's elements are processed in a strictly increasing order, which aligns perfectly with the sequential access provided by an iterator. The in-order traversal can be typically implemented using recursion or a stack.
Steps to Approach:
- Initialization:
- Convert the given tree into a flat structure (like an array or list) representing the in-order traversal. This preprocessing step can be achieved by leveraging a stack where we iteratively push left children, thereby ensuring that we process the smallest element first.
hasNext()andnext():- For
hasNext(), simply check whether there are unvisited elements after the current index. - For
next(), move the internal cursor to the right, and return the value at the new cursor position.
- For
hasPrev()andprev():- For
hasPrev(), verify that the cursor is not at the very start of the in-order traversal. - For
prev(), move the cursor left, returning the value at the cursor.
- For
Effectiveness of Approach:
- The use of a list or array to store in-order elements converts potentially deep tree traversal to simple index operations on an array, enhancing access times for
next()andprev()to constant time, O(1). - Space complexity becomes O(n) due to the storage of the entire tree's nodes in a sequential structure.
- This direct approach conforms to the maximum constraint of operations, efficiently managing repeated calls to navigation methods.
Given the constraints provided which include very high operation counts (up to 105) but with individual operations bounded by constant time, this approach is effective in providing timely responses to iterator queries.
Solutions
- Java
- Python
class BSTTraversal {
Deque<TreeNode> nodeStack;
List<Integer> values;
TreeNode currNode;
int index;
public BSTTraversal(TreeNode root) {
currNode = root;
nodeStack = new ArrayDeque();
values = new ArrayList();
index = -1;
}
public boolean hasNext() {
return !nodeStack.isEmpty() || currNode != null || index < values.size() - 1;
}
public int next() {
++index;
if (index == values.size()) {
while (currNode != null) {
nodeStack.push(currNode);
currNode = currNode.left;
}
TreeNode nextNode = nodeStack.pop();
currNode = nextNode.right;
values.add(nextNode.val);
}
return values.get(index);
}
public boolean hasPrev() {
return index > 0;
}
public int prev() {
--index;
return values.get(index);
}
}
Implement a Binary Search Tree (BST) iterator class in Java that provides forward and backward iteration over the elements of a BST. Below outlines your key implementation steps:
Define essential class members:
- Use
Deque<TreeNode>fornodeStackto keep track of the nodes as you perform an in-order traversal. List<Integer> valuesholds the elements after they have been accessed for easy retrieval in both directions.TreeNode currNodemaintains the current position in the BST.int indexkeeps track of the current position in the listvalues.
- Use
Initialize your iterator with the
BSTTraversal(TreeNode root)constructor:- Start with
currNodeset to therootof the BST. - Initialize
nodeStackas anArrayDeque. - Set
valuesas a newArrayList. - Start
indexat -1 to indicate initial position before the first element.
- Start with
Implement
hasNext()method:- Returns
trueif there are unvisited nodes in the stack, or if the current node is notnull, or if there are more elements to visit invalues.
- Returns
Implement
next()method:- Increment
index. Check ifindexequals the size ofvaluesto determine if traversal to fetch the next value is needed. - Traverse to the next in-order node if required by moving left till possible, then accessing node, moving to right.
- Store each accessed node's value in
values. - Return the current value from
valuesusing the updatedindex.
- Increment
Implement
hasPrev()method:- Returns
trueifindexis greater than 0, indicating there is a previous element.
- Returns
Implement
prev()method:- Decrement
indexand return the value at the newindexfromvalues.
- Decrement
By following these detailed steps, you create a robust implementation of a BST iterator that can move both forward and backward through the elements of a tree, providing flexibility in traversing the data structure.
class BinarySearchTreeIterator:
def __init__(self, root: TreeNode):
self.current = root
self.nodes_stack, self.values = [], []
self.index = -1
def hasNext(self) -> bool:
return self.nodes_stack or self.current or self.index < len(self.values) - 1
def next(self) -> int:
self.index += 1
if self.index == len(self.values):
while self.current:
self.nodes_stack.append(self.current)
self.current = self.current.left
node = self.nodes_stack.pop()
self.current = node.right
self.values.append(node.val)
return self.values[self.index]
def hasPrev(self) -> bool:
return self.index > 0
def prev(self) -> int:
self.index -= 1
return self.values[self.index]
The provided Python code defines a class BinarySearchTreeIterator to efficiently iterate over the elements of a binary search tree (BST) with the additional ability to move backwards. This iterator supports four operations: checking the presence of a next or previous element (hasNext and hasPrev), and retrieving the next or previous element (next and prev).
Initialization:
- The constructor
__init__initializes with a given BST root. It also sets up a listnodes_stackfor node traversal, a listvaluesfor storing accessed node values, and anindexto track the current position in thevalueslist.
- The constructor
hasNextMethod:- This method checks if there are any nodes or values remaining to be accessed. It returns
Trueif traversal can proceed forward, by examining the stack, current node, or index relative to the length ofvalues.
- This method checks if there are any nodes or values remaining to be accessed. It returns
nextMethod:- This method advances the iterator to the next element. It first increments the index. If the index reaches the current length of the
values, the method processes nodes from the stack (implementing in-order traversal) until all direct and right-descendant nodes of the current node are accessed. - The accessed node's value is appended to
valuesand then returned.
- This method advances the iterator to the next element. It first increments the index. If the index reaches the current length of the
hasPrevMethod:- This method checks the possibility of moving backwards by checking if the
indexis greater than 0. It returnsTrueif the iterator can move to a previous element.
- This method checks the possibility of moving backwards by checking if the
prevMethod:- This method retrieves the previous element by decrementing the
indexand returning the value at the new index position fromvalues.
- This method retrieves the previous element by decrementing the
This implementation allows efficient iteration over a BST in forward and backward directions, providing flexibility in navigation while ensuring that every node is processed at most twice.