
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, returningtrue
orfalse
. - 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();
➜ returns3
bSTIterator.next();
➜ returns7
bSTIterator.prev();
➜ returns3
bSTIterator.next();
➜ returns7
bSTIterator.hasNext();
➜ returnstrue
bSTIterator.next();
➜ returns9
bSTIterator.next();
➜ returns15
bSTIterator.next();
➜ returns20
bSTIterator.hasNext();
➜ returnsfalse
bSTIterator.hasPrev();
➜ returnstrue
bSTIterator.prev();
➜ returns15
bSTIterator.prev();
➜ returns9
Constraints
- The number of nodes in the tree is in the range
[1, 105]
. 0 <= Node.val <= 106
- At most
105
calls 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>
fornodeStack
to keep track of the nodes as you perform an in-order traversal. List<Integer> values
holds the elements after they have been accessed for easy retrieval in both directions.TreeNode currNode
maintains the current position in the BST.int index
keeps track of the current position in the listvalues
.
- Use
Initialize your iterator with the
BSTTraversal(TreeNode root)
constructor:- Start with
currNode
set to theroot
of the BST. - Initialize
nodeStack
as anArrayDeque
. - Set
values
as a newArrayList
. - Start
index
at -1 to indicate initial position before the first element.
- Start with
Implement
hasNext()
method:- Returns
true
if 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 ifindex
equals the size ofvalues
to 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
values
using the updatedindex
.
- Increment
Implement
hasPrev()
method:- Returns
true
ifindex
is greater than 0, indicating there is a previous element.
- Returns
Implement
prev()
method:- Decrement
index
and return the value at the newindex
fromvalues
.
- 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_stack
for node traversal, a listvalues
for storing accessed node values, and anindex
to track the current position in thevalues
list.
- The constructor
hasNext
Method:- This method checks if there are any nodes or values remaining to be accessed. It returns
True
if 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
next
Method:- 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
values
and 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
hasPrev
Method:- This method checks the possibility of moving backwards by checking if the
index
is greater than 0. It returnsTrue
if the iterator can move to a previous element.
- This method checks the possibility of moving backwards by checking if the
prev
Method:- This method retrieves the previous element by decrementing the
index
and 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.
No comments yet.