【算法学习】剑指 Offer II 055. 二叉搜索树迭代器|173. 二叉搜索树迭代器(java / c / c++ / python / go / rust)

简介: 实现一个二叉搜索树迭代器类 BSTIterator ,表示一个按中序遍历二叉搜索树(BST)的迭代器: BSTIterator(TreeNode root) 初始化 BSTIterator 类的一个对象。BST 的根节点 root 会作为构造函数的一部分给出。指针应初始化为一个不存在于 BST 中的数字,且该数字小于 BST 中的任何元素。 boolean hasNext() 如果向指针右侧遍历存在数字,则返回 true ;否则返回 false 。 int next() 将指针向右移动,然后返回指针处的数字。注意,指针初始化为一个不存在于 BST 中的数字,所以对

剑指 Offer II 055. 二叉搜索树迭代器|173. 二叉搜索树迭代器:

实现一个二叉搜索树迭代器类 BSTIterator ,表示一个按中序遍历二叉搜索树(BST)的迭代器:

  • BSTIterator(TreeNode root) 初始化 BSTIterator 类的一个对象。BST 的根节点 root 会作为构造函数的一部分给出。指针应初始化为一个不存在于 BST 中的数字,且该数字小于 BST 中的任何元素。
  • boolean hasNext() 如果向指针右侧遍历存在数字,则返回 true ;否则返回 false
  • int next() 将指针向右移动,然后返回指针处的数字。

注意,指针初始化为一个不存在于 BST 中的数字,所以对 next() 的首次调用将返回 BST 中的最小元素。

可以假设 next() 调用总是有效的,也就是说,当调用 next() 时,BST 的中序遍历中至少存在一个下一个数字。

样例 1

在这里插入图片描述

输入
    inputs = ["BSTIterator", "next", "next", "hasNext", "next", "hasNext", "next", "hasNext", "next", "hasNext"]
    inputs = [[[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 是树的高度。

分析

  • 这道算法题考查的就是从 二叉搜索树1 中从小到大取值,也就是中序遍历。
  • 可以直接在初始化时就完成遍历,把值放入队列等数据结构,之后取值和判空就会很快。
  • 但是在初始化时就完成遍历有个缺点,就是如果树很大,但是取值取得比较少,那么开始的初始化就是浪费(道理同 数据延迟加载单例模式的懒汉模式 等),所以我们可以把遍历分摊到每一次取值操作中去。

题解

java

class BSTIterator {
    private TreeNode        cur;
    private Deque<TreeNode> stack;

    public BSTIterator(TreeNode root) {
        cur = root;
        stack = new LinkedList<TreeNode>();
    }

    public int next() {
        while (cur != null) {
            stack.push(cur);
            cur = cur.left;
        }
        cur = stack.pop();
        int val = cur.val;
        cur = cur.right;
        return val;
    }

    public boolean hasNext() {
        return cur != null || !stack.isEmpty();
    }
}

c

typedef struct {
    struct TreeNode *cur;
    struct StackTreeNode *stack[100000];
    int stackSize;
} BSTIterator;


BSTIterator *bSTIteratorCreate(struct TreeNode *root) {
    BSTIterator *iterator = malloc(sizeof(BSTIterator));
    iterator->cur = root;
    iterator->stackSize = 0;
    return iterator;
}

int bSTIteratorNext(BSTIterator *obj) {
    while (obj->cur != NULL) {
        obj->stack[(obj->stackSize)++] = obj->cur;
        obj->cur = obj->cur->left;
    }
    obj->cur = obj->stack[--(obj->stackSize)];
    int val = obj->cur->val;
    obj->cur = obj->cur->right;
    return val;
}

bool bSTIteratorHasNext(BSTIterator *obj) {
    return obj->cur != NULL || obj->stackSize;
}

void bSTIteratorFree(BSTIterator *obj) {
    free(obj);
}

c++

class BSTIterator {
private:
    TreeNode *cur;
    stack<TreeNode *> stacks;
public:
    BSTIterator(TreeNode *root) : cur(root) {
    }

    int next() {
        while (cur != nullptr) {
            stacks.push(cur);
            cur = cur->left;
        }
        cur = stacks.top();
        stacks.pop();
        int val = cur->val;
        cur = cur->right;
        return val;
    }

    bool hasNext() {
        return cur != nullptr || !stacks.empty();
    }
};

python

class BSTIterator:

    def __init__(self, root: TreeNode):
        self.cur = root
        self.stack = []


    def next(self) -> int:
        while self.cur:
            self.stack.append(self.cur)
            self.cur = self.cur.left
        self.cur = self.stack.pop()
        val = self.cur.val
        self.cur = self.cur.right
        return val

    def hasNext(self) -> bool:
        return True if self.cur or self.stack else False

go

type BSTIterator struct {
    cur   *TreeNode
    stack []*TreeNode
}

func Constructor(root *TreeNode) BSTIterator {
    return BSTIterator{cur: root}
}

func (this *BSTIterator) Next() int {
    for this.cur != nil {
        this.stack = append(this.stack, this.cur)
        this.cur = this.cur.Left
    }
    this.cur, this.stack = this.stack[len(this.stack)-1], this.stack[:len(this.stack)-1]
    val := this.cur.Val
    this.cur = this.cur.Right
    return val
}

func (this *BSTIterator) HasNext() bool {
    return this.cur != nil || len(this.stack) > 0
}

rust

use std::{rc::Rc, cell::RefCell};
struct BSTIterator {
  cur: Option<Rc<RefCell<TreeNode>>>,
  stack: Vec<Rc<RefCell<TreeNode>>>
}

impl BSTIterator {

  fn new(root: Option<Rc<RefCell<TreeNode>>>) -> Self {
    BSTIterator {
      cur: root.clone(),
      stack: Vec::new()
    }
  }

  fn next(&mut self) -> i32 {
    while let Some(n) = self.cur.clone() {
      self.stack.push(n.clone());
      self.cur = n.borrow().left.clone();
    };
    self.cur = self.stack.pop();
    let val = self.cur.clone().unwrap().borrow().val;
    self.cur = self.cur.clone().unwrap().borrow().right.clone();
    val
  }

  fn has_next(&self) -> bool {
    self.cur.is_some() || !self.stack.is_empty()
  }
}

原题传送门:https://leetcode-cn.com/problems/kTOapQ/

原题传送门:https://leetcode-cn.com/problems/binary-search-tree-iterator/


非常感谢你阅读本文~
放弃不难,但坚持一定很酷~
希望我们大家都能每天进步一点点~
本文由 二当家的白帽子:https://developer.aliyun.com/profile/sqd6avc7qgj7y 博客原创~


  1. 二叉查找树(Binary Search Tree),(又:二叉搜索树二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为 二叉排序树二叉搜索树作为一种经典的数据结构,它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势;所以应用十分广泛,例如在文件系统和数据库系统一般会采用这种数据结构进行高效率的排序与检索操作。
相关文章
|
1月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
70 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
30天前
|
XML Java 编译器
Java学习十六—掌握注解:让编程更简单
Java 注解(Annotation)是一种特殊的语法结构,可以在代码中嵌入元数据。它们不直接影响代码的运行,但可以通过工具和框架提供额外的信息,帮助在编译、部署或运行时进行处理。
87 43
Java学习十六—掌握注解:让编程更简单
|
15天前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
1月前
|
存储 SQL 小程序
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
这篇文章详细介绍了Java虚拟机(JVM)的运行时数据区域和JVM指令集,包括程序计数器、虚拟机栈、本地方法栈、直接内存、方法区和堆,以及栈帧的组成部分和执行流程。
32 2
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
|
22天前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。
|
1月前
|
小程序 Oracle Java
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
这篇文章是关于JVM基础知识的介绍,包括JVM的跨平台和跨语言特性、Class文件格式的详细解析,以及如何使用javap和jclasslib工具来分析Class文件。
44 0
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
|
1月前
|
存储 算法 Java
带你学习java的数组军队列
带你学习java的数组军队列
35 0
|
6月前
|
存储 算法 Java
【数据结构与算法】1、学习动态数组数据结构(基本模拟实现 Java 的 ArrayList 实现增删改查)
【数据结构与算法】1、学习动态数组数据结构(基本模拟实现 Java 的 ArrayList 实现增删改查)
171 0
|
存储 算法 Java
数据结构算法学习打卡week2 (Java)
数据结构算法学习打卡week2 (Java)
75 0
|
Rust 算法 安全
【算法学习】1588. 所有奇数长度子数组的和(java / c / c++ / python / go / rust)
给你一个正整数数组 arr ,请你计算所有可能的奇数长度子数组的和。 子数组 定义为原数组中的一个连续子序列。 请你返回 arr 中 所有奇数长度子数组的和 。
【算法学习】1588. 所有奇数长度子数组的和(java / c / c++ / python / go / rust)
下一篇
无影云桌面