zoukankan      html  css  js  c++  java
  • LeetCode Notes_#173_二叉搜索树迭代器

    LeetCode Notes_#173_二叉搜索树迭代器

    Contents

    题目

    实现一个二叉搜索树迭代器。你将使用二叉搜索树的根节点初始化迭代器。
    调用 next() 将返回二叉搜索树中的下一个最小的数。
    示例:

    BSTIterator iterator = new BSTIterator(root);
    iterator.next();    // 返回 3
    iterator.next();    // 返回 7
    iterator.hasNext(); // 返回 true
    iterator.next();    // 返回 9
    iterator.hasNext(); // 返回 true
    iterator.next();    // 返回 15
    iterator.hasNext(); // 返回 true
    iterator.next();    // 返回 20
    iterator.hasNext(); // 返回 false

    提示:

    • next() 和 hasNext() 操作的时间复杂度是 O(1),并使用 O(h) 内存,其中 h 是树的高度。
    • 你可以假设 next() 调用总是有效的,也就是说,当调用 next() 时,BST 中至少存在一个下一个最小的数。

    思路分析

    迭代数字的顺序是从小到大,也就是BST的中序遍历的顺序。

    方法1:在构造器中得到中序遍历序列

    写一个中序遍历的辅助方法,在构造器中调用它,把中序遍历序列保存下来。next()方法只需要按顺序访问中序遍历序列的每个数字即可。
    但是空间复杂度不符合要求。

    方法2:拆分非递归中序遍历模板

    其实就是非递归中序遍历二叉树的变体,只需要把代码拆分到三个方法当中即可。
    以下是非递归中序遍历的模板。

    class Solution {
        public List<Integer> inOrderTraversal(TreeNode root) {
            if (root == null) {
                return new LinkedList<>();
            }
            List<Integer> res = new LinkedList<>();
            Deque<TreeNode> stack = new LinkedList<>();
            TreeNode node = root;
            //以上属于初始化部分,写在构造器中
            //以下一行是循环终止条件,写在hasNext()中
            while(node != null || !stack.isEmpty()) {
            //以下是循环体,写在next()中
                while (node != null) {
                    stack.addLast(node);
                    node = node.left;
                }
                node = stack.removeLast();
                res.add(node.val);
                node = node.right;
            }
            return res;
        }
    }

    模板大法好。

    解答

    解答1:在构造器中得到中序遍历序列

    不符合空间复杂度要求,仅供参考。

    class BSTIterator {
        List<Integer> inorder;
        int index = 0;
    
        public BSTIterator(TreeNode root) {
            inorder = new ArrayList<>();
            inorderRecur(root);
        }
    
        //得到中序遍历序列
        private void inorderRecur(TreeNode root){
            if(root == null) return;
            inorderRecur(root.left);
            inorder.add(root.val);
            inorderRecur(root.right);
        }
        
        //返回当前节点的值;然后index增加1,指向下一节点
        /** @return the next smallest number */
        public int next() {
            return inorder.get(index++);
        }
        
        //判断当前的index索引是否越界
        /** @return whether we have a next smallest number */
        public boolean hasNext() {
            return index <= inorder.size() - 1;
        }
    }

    复杂度分析

    构造器
    时间复杂度:O(n)
    空间复杂度:O(n)
    next(),hasNext()方法
    时间复杂度:O(1)
    空间复杂度:O(n),因为借助了额外的inorder数组。
    所以是不符合题目要求的,因为题目要求空间复杂度是O(h)

    解答2:拆分非递归中序遍历模板

    //对非递归中序遍历模板进行简单的拆分即可
    class BSTIterator {
        TreeNode node;
        LinkedList<TreeNode> stack;
        //初始化部分写到构造器当中
        public BSTIterator(TreeNode root) {
            node = root;
            stack = new LinkedList<>();
        }
        //next()方法其实就是中序遍历的循环体
        /** @return the next smallest number */
        public int next() {
            while(node != null){
                stack.addLast(node);
                node = node.left;
            }
            node = stack.removeLast();
            int val = node.val;
            node = node.right;
            return val;
        }
        //hasNext()方法就是中序遍历的循环条件
        /** @return whether we have a next smallest number */
        public boolean hasNext() {
            return node != null || !stack.isEmpty();
        }
    }

    复杂度分析

    时间复杂度

    • next():所有的n个节点都会入栈,但是并不是每次调用next就入栈一个,有时候调用一次next入栈多个节点,有时候则没有节点入栈。整体来看,next()被调用n次,总共入栈n个节点,平均下来是O(1)
    • hasNext():这个就不用说了,每次调用的复杂度都是O(1)

    空间复杂度:O(h)

    • 虽然所有的n个节点都入栈,但是栈中元素最多只有h(即树的深度)。
    • 栈中元素最多的时候就是刚开始将最左边的一溜全部入栈的时候,刚好是h。
  • 相关阅读:
    MAUI预览版发布 (.NET 6 Preview2)
    ASP.NET Core 基础系列(6)(中间件)
    ASP.NET Core 基础系列(5)(appSetting)
    ASP.NET Core 基础系列(4)(Startup)
    ASP.NET Core 基础系列(3)(启动设置)
    ASP.NET Core 基础系列(2)(托管模型)
    ASP.NET Core 基础系列(1)(Main方法)
    Android开发学习之路-PopupWindow和仿QQ左滑删除
    部分病毒进程任务管理器终止不怎么办
    intellij idea 历史版本下载地址
  • 原文地址:https://www.cnblogs.com/Howfars/p/13463909.html
Copyright © 2011-2022 走看看