Leetcode: Binary Search Tree Iterator


Leetcode: Binary Search Tree Iterator
Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the root node of a BST.
Calling next() will return the next smallest number in the BST.
Note: next() and hasNext() should run in average O(1) time and uses O(h) memory, where h is the height of the tree.
这是一道很经典的题目,考的非递归的中序遍历。其实这道题等价于写一个二叉树中序遍历的迭代器。需要内置一个栈,一开始先存储到最左叶子节点的路径。在遍历的过程中,只要当前节点存在右孩子,则进入右孩子,存除从此处开始到当前子树里最左叶子节点的路径。
  1. public class BSTIterator {  
  2.     Stack<TreeNode> stack;  
  3.   
  4.     public BSTIterator(TreeNode root) {  
  5.         stack = new Stack<TreeNode>();  
  6.         while (root != null) {  
  7.             stack.push(root);  
  8.             root = root.left;  
  9.         }  
  10.     }  
  11.   
  12.     /** @return whether we have a next smallest number */  
  13.     public boolean hasNext() {  
  14.         return !stack.isEmpty();  
  15.     }  
  16.   
  17.     /** @return the next smallest number */  
  18.     public int next() {  
  19.         TreeNode node = stack.pop();  
  20.         int ret = node.val;  
  21.         if (node.right != null) {  
  22.             node = node.right;  
  23.             while (node != null) {  
  24.                 stack.push(node);  
  25.                 node = node.left;  
  26.             }  
  27.         }  
  28.         return ret;  
  29.     }  

Your solution is indeed average O(1) time and O(h) space.
Each node will be visited at most twice-> average O(1) run time.
The stack will store at most h nodes -> O(h) space.
public class BSTIterator {
    private Stack<TreeNode> stack = new Stack<TreeNode>();

    public BSTIterator(TreeNode root) {
        pushAll(root);
    }

    /** @return whether we have a next smallest number */
    public boolean hasNext() {
        return !stack.isEmpty();
    }

    /** @return the next smallest number */
    public int next() {
        TreeNode tmpNode = stack.pop(); // handle when stack is empty
        pushAll(tmpNode.right);
        return tmpNode.val;
    }

    private void pushAll(TreeNode node) {
        for (; node != null; stack.push(node), node = node.left);
    }
}
The complexity of the "hasNext()" is O(1). While the "next()" needs to refresh the stack, which in the best case (leaf) takes constant time, and in the worst case, it would take up to "h"steps. The overall cost of "next()" is then amortized over the number of nodes. I don't have the precise proof, but it seems to be O(1) on average.
//refreshStack reuse the code
Stack<TreeNode> stack = new Stack<TreeNode>(); private void refreshStack(TreeNode iter){ while(iter != null){ stack.push(iter); iter = iter.left; } } public BSTIterator(TreeNode root) { this.refreshStack(root); } /** @return whether we have a next smallest number */ public boolean hasNext() { return !(stack.isEmpty()); } /** @return the next smallest number */ public int next() { TreeNode node = stack.pop(); if(node != null){ this.refreshStack(node.right); return node.val; } return -1; // should throw exception here. }
X.
https://leetcode.com/discuss/22137/my-java-accepted-solution

public class Solution {
    private Stack<TreeNode> stack = new Stack<>();
    private TreeNode curt;
    
    // @param root: The root of binary tree.
    public Solution(TreeNode root) {
        curt = root;
    }

    //@return: True if there has next node, or false
    public boolean hasNext() {
        return (curt != null || !stack.isEmpty());
    }
    
    //@return: return next node
    public TreeNode next() {
        while (curt != null) {
            stack.push(curt);
            curt = curt.left;
        }
        
        curt = stack.pop();
        TreeNode node = curt;
        curt = curt.right;
        
        return node;
    }
}
http://www.cnblogs.com/yuzhangcmu/p/4197346.html
Python code:
http://bookshadow.com/weblog/2014/12/31/leetcode-binary-search-tree-iterator/
Implement In-order Iterator for Binary Tree
http://n00tc0d3r.blogspot.com/2013/08/implement-iterator-for-binarytree-i-in.html
public class InOrderBinaryTreeIteratorImpl implements InOrderBinaryTreeIterator {
   Stack<TreeNode> stack = new Stack<TreeNode>();
 
   /** Push node cur and all of its left children into stack */
   private void pushLeftChildren(TreeNode cur) {
     while (cur != null) {
       stack.push(cur);
       cur = cur.left;
     }
   }

   public InOrderBinaryTreeIterator(TreeNode root) {
     pushLeftChildren(root);
   }
   public boolean hasNext() {
     return !stack.isEmpty();
   }
   public Integer next() {
     if (!hasNext()) {
       throw new NoSuchElementException("All nodes have been visited!");
     }
 
     TreeNode res = stack.pop();
     pushLeftChildren(res.right);
 
     return res.val;
   }
   public void remove() {
     throw new UnsupportedOperationException("remove() is not supported.");
   }
 }

  public ArrayList<Integer> inorderTraversal(TreeNode root) {
   InOrderBinaryTreeIterator iterator = new InOrderBinaryTreeIteratorImpl(root);
   ArrayList<Integer> results = new ArrayList<Integer>();
   while (iterator.hasNext()) {
     results.add(iterator.next());
   }
   return results;  
 }

X. O(1) space and O(1) amortized time, using Morris Tree Traversal
https://leetcode.com/discuss/58469/solution-space-amortized-time-using-morris-tree-traversal
https://leetcode.com/discuss/23721/morris-traverse-solution

Construct Period

The idea is use in-order Morris Tree Traversal (check out [1][2] if you are not familiar with it, otherwise the bellow explanation to you is nonsense) to construct a threaded binary tree in construct function. (This is O(n) time, but we don't care much about it.) Then set a pointer (we call it "curr") to the smallest TreeNode, which is easy to do, just find the left-most child from root.

hasNext()

For hasNext() function, simple return "curr != null", which is by definition of threaded binary tree.

next()

For next() function, it is a little bit tricky. We call the right child of "curr" as "next". If "next" is not a normal right child of "curr", which means the right child relationship is constructed during the threaded binary tree construction period, then the next TreeNode we should iterate is indeed "next". However, if "next" is a normal right child of "curr", then the next TreeNode we should iterate is actually the left-most child of "next".
So the problem reduces to how to make clear the situation. Well, it is no hard. If "next" is null, then we've done, simply set "curr" to null. If "next" has no left child, or "next"'s left child is strictly larger than "curr", that means it is a normal right child of "curr", so we should set "curr" to left-most child of "next". Otherwise, we set "curr" to "next", and break the right child relationship between "curr" and "next", to recover the original tree structure.

Complexity analysis

The space complexity is straightforwardly O(1). The time complexity needs some more explanation. Since the only part that is not O(1) is when we search the left-most child of "next". However, for all the children along this left path (say, there are N children), we do once search left-most and (N-1) times simply go to right child. So the amortized time complexity is still O(1).
public class BSTIterator { private TreeNode curr; public BSTIterator(TreeNode root) { TreeNode prev; //Do a morris in-order traversal, to construct a threaded binary tree curr = root; while(curr != null){ if(curr.left == null){ curr = curr.right; } else{ prev = curr.left; while(prev.right != null && prev.right != curr) prev = prev.right; if(prev.right == null){ prev.right = curr; curr = curr.left; } else{ curr = curr.right; } } } //get the left-most child of root, i.e. the smallest TreeNode curr = root; while(curr != null && curr.left != null) curr = curr.left; } /** @return whether we have a next smallest number */ public boolean hasNext() { return curr != null; } /** @return the next smallest number */ public int next() { //copy the value we need to return int result = curr.val; TreeNode next = curr.right; if(next == null) curr = next; //the right child relationship is a normal one, find left-most //child of "next" else if(next.left == null || next.left.val > curr.val){ curr = next; while(curr.left != null) curr = curr.left; } //the right child relationship is made when we //construct the threaded binary tree else{ curr.right = null;//we recover the original tree structure curr = next; } return result; } }

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts