二叉搜索树迭代器

本文探讨了如何优化二叉搜索树迭代器的实现,通过迭代而非递归生成中序遍历,并利用单调栈技巧,实现在平均O(1)时间和O(h)空间复杂度下高效完成next()和hasNext()操作,适用于高度为h的树结构。
摘要由CSDN通过智能技术生成

此题解仅代表个人在写题时的所思所想,如有朋友们看到了我理解不到位的地方,欢迎指正。看到了其他精妙的解法后我也会进行学习且理解,就当我个人的学习笔记看看就好了,求轻喷O(∩_∩)O

题目描述

二叉搜索树迭代器
实现一个二叉搜索树迭代器类BSTIterator ,表示一个按中序遍历二叉搜索树(BST)的迭代器:
BSTIterator(TreeNode root) 初始化 BSTIterator 类的一个对象。BST 的根节点 root 会作为构造函数的一部分给出。指针应初始化为一个不存在于 BST 中的数字,且该数字小于 BST 中的任何元素。
boolean hasNext() 如果向指针右侧遍历存在数字,则返回 true ;否则返回 false 。
int next()将指针向右移动,然后返回指针处的数字。
注意,指针初始化为一个不存在于 BST 中的数字,所以对 next() 的首次调用将返回 BST 中的最小元素。
你可以假设 next() 调用总是有效的,也就是说,当调用 next() 时,BST 的中序遍历中至少存在一个下一个数字。
示例:
输入
[“BSTIterator”, “next”, “next”, “hasNext”, “next”, “hasNext”, “next”, “hasNext”, “next”, “hasNext”]
[[[7, 3, 15, null, null, 9, 20]], [], [], [], [], [], [], [], [], []]
输出
[null, 3, 7, true, 9, true, 15, true, 20, false]

解释
BSTIterator bSTIterator = new BSTIterator([7, 3, 15, null, null, 9, 20]);
bSTIterator.next(); // 返回 3
bSTIterator.next(); // 返回 7
bSTIterator.hasNext(); // 返回 True
bSTIterator.next(); // 返回 9
bSTIterator.hasNext(); // 返回 True
bSTIterator.next(); // 返回 15
bSTIterator.hasNext(); // 返回 True
bSTIterator.next(); // 返回 20
bSTIterator.hasNext(); // 返回 False
提示:
树中节点的数目在范围 [1, 105] 内
0 <= Node.val <= 106
最多调用 105 次 hasNext 和 next 操作
进阶:
你可以设计一个满足下述条件的解决方案吗?next() 和 hasNext() 操作均摊时间复杂度为 O(1) ,并使用 O(h) 内存。其中 h 是树的高度。

算法思路

解法一:初始化迭代器时便根据根节点初始化一个记录树中序遍历的数组

标题题目要求是表示一个按中序遍历二叉搜索树(BST)的迭代器,而一棵树的中序遍历的顺序是固定的,最朴素的想法便是初始化迭代器的时候,根据给定的根节点,生成一个数组表示该树的中序遍历,在后续的操作中对该数组进行操作即可,不必再去对树进行搜索。

时间复杂度:O(N)
空间复杂度:O(N)

该解法最大的缺陷便是在每次初始化中序遍历数组时都要遍历树的每一个节点,即使我们需要进行的操作只是对树的某些节点进行操作,都要遍历整棵树用于生成中序遍历数组,容易造成时间上的极大浪费,所以不是最好的解法,那么有没有一种解法可以解决这一问题,将此解法中的递归转换为迭代呢?

解法二:单调栈+迭代

为了解决上述解法一存在的问题,更加省时地节约时间,我们必须将上述程序中的树的遍历的递归优化为迭代的方法解决。

而将递归优化为迭代,最基本思路便是借用数据结构——栈来实现。再加上此树为二叉搜索树,比较轻松便能想到单调栈。

所以针对这题的写法,总体思路便为栈中只保留左节点。以下为具体流程:

  1. 把根节点和它的所有左节点都放入栈中。

  2. 若栈顶节点没有右节点,其本身又是最左节点,那么代表它即是下一个将要弹出的节点,调用next()方法弹出此节点,但如果他有右子树,则把相应的右子树的所有左节点放入栈中(类似于第一步的操作只不过换了一个更小的树,这样就能保证能够按序遍历所有的节点)。

    个人通俗理解:将所有的左节点存放到栈中,只用记录树的“左半部分”,如果该左半部分有右子树的话,便将右子树作为新的树一分为二,只需考虑右半部分的树的输出以及子树根节点的输出即可。

时间复杂度:O(1)

空间复杂度:O(h),h为树的高度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值