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。
  • 相关阅读:
    623. Add One Row to Tree 将一行添加到树中
    771. Jewels and Stones 珠宝和石头
    216. Combination Sum III 组合总数三
    384. Shuffle an Array 随机播放一个数组
    382. Linked List Random Node 链接列表随机节点
    向github项目push代码后,Jenkins实现其自动构建
    centos下安装Jenkins
    python提取批量文件内的指定内容
    批处理实现:批量为文件添加注释
    python抓取每期双色球中奖号码,用于分析
  • 原文地址:https://www.cnblogs.com/Howfars/p/13463909.html
Copyright © 2011-2022 走看看