173. Binary Search Tree Iterator
Implement the BSTIterator class that represents an iterator over the in-order traversal of a binary search tree (BST):
BSTIterator(TreeNode root)Initializes an object of theBSTIteratorclass. Therootof the BST is given as part of the constructor. The pointer should be initialized to a non-existent number smaller than any element in the BST.boolean hasNext()Returnstrueif there exists a number in the traversal to the right of the pointer, otherwise returnsfalse.int next()Moves the pointer to the right, then returns the number at the pointer.
Notice that by initializing the pointer to a non-existent smallest number, the first call to next() will return the smallest element in the BST.
You may assume that next() calls will always be valid. That is, there will be at least a next number in the in-order traversal when next() is called.
Example 1:

Input
["BSTIterator", "next", "next", "hasNext", "next", "hasNext", "next", "hasNext", "next", "hasNext"]
[[[7, 3, 15, null, null, 9, 20]], [], [], [], [], [], [], [], [], []]
Output
[null, 3, 7, true, 9, true, 15, true, 20, false]
Explanation
BSTIterator bSTIterator = new BSTIterator([7, 3, 15, null, null, 9, 20]);
bSTIterator.next(); // return 3
bSTIterator.next(); // return 7
bSTIterator.hasNext(); // return True
bSTIterator.next(); // return 9
bSTIterator.hasNext(); // return True
bSTIterator.next(); // return 15
bSTIterator.hasNext(); // return True
bSTIterator.next(); // return 20
bSTIterator.hasNext(); // return False
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, andnext.
Follow up:
- Could you implement
next()andhasNext()to run in averageO(1)time and useO(h)memory, wherehis the height of the tree?
Solution:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class BSTIterator {
Deque<TreeNode> queue = new ArrayDeque<>();
public BSTIterator(TreeNode root) {
dfsLeft(root);
}
private void dfsLeft(TreeNode root){
while(root != null){
queue.offerLast(root);
root = root.left;
}
}
public int next() {
TreeNode root = queue.pollLast();
int result = root.val;
root = root.right;
dfsLeft(root);
return result;
}
public boolean hasNext() {
if (queue.isEmpty()){
return false;
}else{
return true;
}
}
}
/**
* Your BSTIterator object will be instantiated and called as such:
* BSTIterator obj = new BSTIterator(root);
* int param_1 = obj.next();
* boolean param_2 = obj.hasNext();
*/
- 时间复杂度:由于每个元素都是严格「进栈」和「出栈」一次,复杂度为均摊 O(1)
- 空间复杂度:栈内最多保存与深度一致的节点数量,复杂度为 O(h)
基本思路 这道题本质上考的是「将迭代版的中序遍历代码」做等价拆分。
我们知道,中序遍历的基本逻辑是:处理左子树 -> 处理当前节点 -> 处理右子树。
其中迭代做法是利用「栈」进行处理:
先将当前节点的所有左子树压入栈,压到没有为止 将最后一个压入的节点弹出(栈顶元素),加入答案 将当前弹出的节点作为当前节点,重复步骤一
class Solution {
List<Integer> ans = new ArrayList<>();
Deque<TreeNode> d = new ArrayDeque<>();
public List<Integer> inorderTraversal(TreeNode root) {
while (root != null || !d.isEmpty()) {
// 步骤 1
while (root != null) {
d.addLast(root);
root = root.left;
}
// 步骤 2
root = d.pollLast();
ans.add(root.val);
// 步骤 3
root = root.right;
}
return ans;
}
}
首先因为 next() 方法中我们需要输出一个值,执行的的是「步骤 2」的逻辑,同时我们需要在其前后添加「步骤 1」和「步骤 3」。
另外,我们还有一个 hasNext() 要处理,显然 hasNext() 应该对应我们的栈是否为空。
为此,我们需要确保每次输出之后「步骤 1」被及时执行。
综上,我们应该在初始化时,走一遍「步骤 1」,然后在 next() 方法中走「步骤 2」、「步骤 3」和「步骤 1」。