Binary Search Tree Iterator II

medium tree bst stack design

Problem

Design an iterator over a binary search tree that walks values in in-order (ascending) and can move in both directions. Support next() and prev() to return the next or previous value, plus hasNext() and hasPrev() to test availability.

The iterator starts positioned before the first element, so the first next() returns the smallest value. We expand the tree lazily and cache values already produced so prev() can replay them without re-walking.

Inputtree = [7,3,15,null,null,9,20]; ops = next, next, prev, next, hasNext
Output3, 7, 3, 7, true
In-order is 3, 7, 9, 15, 20. next→3, next→7, prev→3, next→7, and 9 still remains so hasNext is true.

class BSTIterator:
    def __init__(self, root):
        self.stack = []
        self.arr = []
        self.pos = -1
        self._push_left(root)

    def _push_left(self, node):
        while node:
            self.stack.append(node)
            node = node.left

    def hasNext(self):
        return self.pos < len(self.arr) - 1 or bool(self.stack)

    def next(self):
        self.pos += 1
        if self.pos == len(self.arr):
            node = self.stack.pop()
            self.arr.append(node.val)
            self._push_left(node.right)
        return self.arr[self.pos]

    def hasPrev(self):
        return self.pos > 0

    def prev(self):
        self.pos -= 1
        return self.arr[self.pos]
class BSTIterator {
  constructor(root) {
    this.stack = [];
    this.arr = [];
    this.pos = -1;
    this.pushLeft(root);
  }
  pushLeft(node) {
    while (node) { this.stack.push(node); node = node.left; }
  }
  hasNext() {
    return this.pos < this.arr.length - 1 || this.stack.length > 0;
  }
  next() {
    this.pos++;
    if (this.pos === this.arr.length) {
      const node = this.stack.pop();
      this.arr.push(node.val);
      this.pushLeft(node.right);
    }
    return this.arr[this.pos];
  }
  hasPrev() { return this.pos > 0; }
  prev() { this.pos--; return this.arr[this.pos]; }
}
class BSTIterator {
    private Deque<TreeNode> stack = new ArrayDeque<>();
    private List<Integer> arr = new ArrayList<>();
    private int pos = -1;
    public BSTIterator(TreeNode root) { pushLeft(root); }
    private void pushLeft(TreeNode node) {
        while (node != null) { stack.push(node); node = node.left; }
    }
    public boolean hasNext() {
        return pos < arr.size() - 1 || !stack.isEmpty();
    }
    public int next() {
        pos++;
        if (pos == arr.size()) {
            TreeNode node = stack.pop();
            arr.add(node.val);
            pushLeft(node.right);
        }
        return arr.get(pos);
    }
    public boolean hasPrev() { return pos > 0; }
    public int prev() { pos--; return arr.get(pos); }
}
class BSTIterator {
    stack<TreeNode*> st;
    vector<int> arr;
    int pos = -1;
    void pushLeft(TreeNode* node) {
        while (node) { st.push(node); node = node->left; }
    }
public:
    BSTIterator(TreeNode* root) { pushLeft(root); }
    bool hasNext() { return pos < (int)arr.size() - 1 || !st.empty(); }
    int next() {
        pos++;
        if (pos == (int)arr.size()) {
            TreeNode* node = st.top(); st.pop();
            arr.push_back(node->val);
            pushLeft(node->right);
        }
        return arr[pos];
    }
    bool hasPrev() { return pos > 0; }
    int prev() { pos--; return arr[pos]; }
};
Time: O(1) amortized Space: O(n)