题目地址:
https://www.lintcode.com/problem/binary-search-tree-iterator/
给定一个BST,设计其中序遍历的iterator。
思路是模仿二叉树的非递归中序遍历。用一个节点指针cur来保存当前需要中序遍历的子树的根,然后用一个栈来模拟递归。当调用next()
方法时,也就是要开始中序遍历cur这个子树,那么应当返回的当然是cur一路向左走到的最后一个节点node,并且下一个要中序遍历的子树就是node的右子树,所以将cur赋值为node的右子树的根;如果cur本身是null,说明以cur为右子树根的那棵子树遍历完了,也就意味着这棵子树也中序遍历完了,那么下一个要返回的节点应当是node的父亲节点,并且下一个要中序遍历的子树是node的父亲节点的右子树,所以将cur赋值为node父亲的右子树的根。显然hasNext()
返回true说明还有节点没访问完,意味着要么接下来要访问的右子树cur不为空,要么cur的父亲这棵子树访问完后还有树根要访问,而这个树根就是栈顶。所以其返回true当且仅当cur不为null或者栈不空。代码如下:
import java.util.ArrayDeque;
import java.util.Deque;
public class BSTIterator {
private Deque<TreeNode> stack;
// cur存放的是接下来要中序遍历的子树的树根
private TreeNode cur;
/*
* @param root: The root of binary tree.
*/
public BSTIterator(TreeNode root) {
// do intialization if necessary
stack = new ArrayDeque<>();
// 一开始要中序遍历的子树当然就是树本身,树根就是root
cur = root;
}
/*
* @return: True if there has next node, or false
*/
public boolean hasNext() {
// write your code here
return cur != null || !stack.isEmpty();
}
/*
* @return: return next node
*/
public TreeNode next() {
// write your code here
// 如果接下来要遍历的子树非空,那么按照中序遍历的原则,应当返回其最左边的节点
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
// 下次调用next时,要遍历的子树的根应当是右子树根
cur = stack.peek().right;
return stack.pop();
}
}
class TreeNode {
int val;
TreeNode left, right;
TreeNode(int x) {
val = x;
}
}
hasNext()
的时间复杂度
O
(
1
)
O(1)
O(1),next()
的时间复杂度是
O
(
h
)
O(h)
O(h),均摊复杂度是
O
(
1
)
O(1)
O(1);空间复杂度
O
(
h
)
O(h)
O(h)。
均摊复杂度 O ( 1 ) O(1) O(1)的理由是,每个节点都只会入栈出栈各一次,所以遍历完整棵树的复杂度是 O ( n ) O(n) O(n),而遍历完整棵树的操作次数是 n n n次,所以均摊下来每次操作时间 O ( 1 ) O(1) O(1)。