引言
力扣题目【二叉搜索树迭代器】描述 -> 传送门
所用语言:Java
执行用时 22 ms,内存消耗 42.1 MB
正文
先插个题外话,你要明白什么是二叉搜索树。虽然对解这道题没啥帮助,但是对你自己在力扣上写测试用例是有帮助的
先说说题目的几点要求
- 题目要求使用中序遍历,即,先遍历左结点,然后到中间结点,然后再是右结点
- 题目要求
next()
和hasNext()
的操作均摊时间复杂度为 O(1),你有可能想到了要把二叉搜索树转化一下,把结点按照顺序存到栈、队列、链表、数组等。等到需要next()
操作的时候,直接取,而不用遍历树了 - 另外,题目要求使用 O(h) 内存。其中 h 是树的高度。这就限制了我们应该如何存储结点
按照我最开始的思路
- 打算用栈来存储二叉搜索树的结点
- 栈的特性是后进先出,所以我打算从根结点开始,按照中序遍历的方式把沿途经过的结点放到栈中
- 但是如果是一下子遍历完全部结点,把全部结点都存储起来的话,就不满足使用 O(h) 内存的要求了。所以,便有了以下的优化,并且操作起来更简单:
- ①在初始化迭代器类
BSTIterator
的时候,从根节点开始,沿着最左边的路径一路走到底,并把沿途经过的结点依次放入栈中 - ②当调用了
next()
操作时,从栈顶弹出一个结点A,然后以这个结点A的右结点为根节点,又沿着最左边的路径一路走到底,并把沿途经过的结点依次放入栈中。然后返回结点A的值val
- ③如果是调用了
hasNext()
操作时,则判断一下栈是否为空就行了。如果栈为空,就返回false
,如果栈不为空,就返回true
- ①在初始化迭代器类
按照思路给个示例
现在有一棵二叉搜索树:
I. 初始化之后,栈中的元素为 [2, 5, 12]
(左边为栈顶)
II. 调用 next()
之后,栈中的元素为 [5, 12]
(左边为栈顶)
III. 调用 next()
之后,栈中的元素为 [9, 12]
(左边为栈顶)
IV. 调用 next()
之后,栈中的元素为 [12]
(左边为栈顶)
V. 调用 next()
之后,栈中的元素为 [15, 18]
(左边为栈顶)
…
…
答案
class BSTIterator {
private ArrayDeque<TreeNode> queue = new ArrayDeque<>();
// private LinkedList<TreeNode> list = new LinkedList<>();
// private int count = -1;
// private Stack<TreeNode> stack = new Stack<TreeNode>();
public BSTIterator(TreeNode root) {
goToLeft(root);
}
public int next() {
// TreeNode temp = stack.pop();
// goToLeft(temp.right);
// return temp.val;
// TreeNode temp = list.remove(count--);
// goToLeft(temp.right);
// return temp.val;
TreeNode temp = queue.pop();
goToLeft(temp.right);
return temp.val;
}
public boolean hasNext() {
// return !stack.empty();
// return count > -1;
return !queue.isEmpty();
}
/**
* 往左走到底
*/
private void goToLeft(TreeNode node) {
// if (node != null) {
// stack.push(node);
// goToLeft(node.left);
// } else {
// return ;
// }
// if (node != null) {
// list.add(node);
// count++;
// goToLeft(node.left);
// } else {
// return ;
// }
if (node != null) {
queue.push(node);
goToLeft(node.left);
} else {
return ;
}
}
}
在上面的代码示例中,我用了三种数据结构:
- 一个是 Java 的
Stack
,但是效率很低,执行时间久,内存消耗也高。已经十分不推荐使用 Java 中的Stack
了,这是旧时代的遗留物 - 一个是
LinkedList
,效率明显高多了 - 一个是
ArrayDeque
,在这里面我把它也当成一个栈来使用,但是效率比Stack
高多了
最后
还是依旧的,如果能有更好的方法,希望大家可以分享一下💗
另外,我的这个答案不是一个规范的迭代器,大家可以改进一下