Check for Identical BSTs without building the trees | GeeksforGeeks


Check for Identical BSTs without building the trees | GeeksforGeeks
Given two arrays which represent a sequence of keys. Imagine we make a Binary Search Tree (BST) from each array. We need to tell whether two BSTs will be identical or not without actually constructing the tree.
a[] = {2, 4, 1, 3} will construct following tree.
   2
 /  \
1    4
    /
   3
b[] = {2, 4, 3, 1} will also also construct the same tree.
   2
 /  \
1    4
    /
   3 
So the output is "True"
就是把这个数组里面的元素一个一个地插入到一个初始为空的BST里面,后面的便是利用BST的特性和递归的思想了.Alternative Solution from http://tech-queries.blogspot.com/2011/06/check-if-identical-bsts-from-given.html
Check if stream is finished if yes -> return false
Check if both the stream has same number of elements, if not -> return false
Check if root is same, if not -> return false
leftsubtree arrays = constructed from smaller elements than root
rightsubtree arrays = constructed from greater elements than root
if leftsubtree == rightsubtree -> return true
For finding result in step 6, follow above steps recursively
def checkidenticaltree(a, b):
   if len(a) != len(b):
       return False
   if a[0] != b[0]:
       return False
   if len(a) <= 1:
       return True

   a_left  = []
   a_right = []
   for x in a:
       if x < a[0]:
           a_left.append(x)
       elif x > a[0]:
           a_right.append(x)

   b_left  = []
   b_right = []
   for x in b:
       if x < b[0]:
           b_left.append(x)
       elif x > b[0]:
           b_right.append(x)
   return checkidenticaltree(a_right, b_right) and checkidenticaltree(a_left, b_left)



According to BST property, elements of left subtree must be smaller and elements of right subtree must be greater than root.
Two arrays represent sane BST if for every element x, the elements in left and right subtrees of x appear after it in both arrays. And same is true for roots of left and right subtrees.
The idea is to check of if next smaller and greater elements are same in both arrays. Same properties are recursively checked for left and right subtrees. The idea looks simple, but implementation requires checking all conditions for all element.



I think the complexity of the above algorithm is O(n^2) consider the case when the arrays are of the form
arr1=[root,[ permutation of left subtree][ permutation of right subtree]]
arr2=[root,[ permutation of left subtree][ permutation of right subtree]]
and the the BST is a complete binary tree . here we are going to traverse the permutation of right subtree for every leaf of the left subtree so 
leaf in left subtree = O(n)
nodes in right sub tree = O(n) 
so O(n^2)

    /* The main function that checks if two arrays a[] and b[] of size n construct
      same BST. The two values 'min' and 'max' decide whether the call is made for
      left subtree or right subtree of a parent element. The indexes i1 and i2 are
      the indexes in (a[] and b[]) after which we search the left or right child.
      Initially, the call is made for INT_MIN and INT_MAX as 'min' and 'max'
      respectively, because root has no parent.
      i1 and i2 are just after the indexes of the parent element in a[] and b[]. */
    bool isSameBSTUtil(int a[], int b[], int n, int i1, int i2, int min, int max)
    {
       int j, k;
       /* Search for a value satisfying the constraints of min and max in a[] and
          b[]. If the parent element is a leaf node then there must be some
          elements in a[] and b[] satisfying constraint. */
       for (j=i1; j<n; j++)
           if (a[j]>min && a[j]<max)
               break;
       for (k=i2; k<n; k++)
           if (b[k]>min && b[k]<max)
               break;
       /* If the parent element is leaf in both arrays */
       if (j==n && k==n)
           return true;
       /* Return false if any of the following is true
          a) If the parent element is leaf in one array, but non-leaf in other.
          b) The elements satisfying constraints are not same. We either search
             for left child or right child of the parent element (decinded by min
             and max values). The child found must be same in both arrays */
       if (((j==n)^(k==n)) || a[j]!=b[k])
           return false;
       /* Make the current child as parent and recursively check for left and right
          subtrees of it. Note that we can also pass a[k] in place of a[j] as they
          are both are same */
       return isSameBSTUtil(a, b, n, j+1, k+1, a[j], max) &&  // Right Subtree
              isSameBSTUtil(a, b, n, j+1, k+1, min, a[j]);    // Left Subtree
    }
    // A wrapper over isSameBSTUtil()
    bool isSameBST(int a[], int b[], int n)
    {
       return isSameBSTUtil(a, b, n, 0, 0, INT_MIN, INT_MAX);
    }
    By the definition of BST, all nodes in the left sub-tree is smaller than the root, and all elements of the right sub-tree is greater than the root. So, 2 arrays will construct the same BST if the 1st element of both arrays are the same, and this is recursively true for elements smaller than the 1st element for both arrays and also for elements bigger than the 1st element for both arrays. One thing to remember that when constructing these small arrays (smaller and bigger elements) you should preserve the original order of the elements. Take a look at `calculateSlow` function for this implementation.
    Now, this algorithm can be improved without constructing the sub-arrays. The details can be found in the original link.
    public static boolean calculate(int []a, int []b){
      return calculateRecursive(a, b, 0, 0, Integer.MIN_VALUE, Integer.MAX_VALUE);
    }
    private static boolean calculateRecursive(int []a,int []b, int i_a, int j_b, int min, int max){
      int i;
      int j;
      for(i=i_a;i&lt;a.length;i++)
        if(a[i]&gt;min && a[i]&lt;max) break;
      for(j=j_b;j&lt;b.length;j++)
        if(b[j]&gt;min && b[j]&lt;max) break;
      if(i==a.length && j==b.length) //if does not hit the break then i is now a.length
        return true;
      else if(i==a.length || j==b.length)
        return false;
      else 
        return a[i]==b[j] && calculateRecursive(a,b,i+1,j+1,min,a[i]) && calculateRecursive(a,b,i+1,j+1,a[i],max);
    }
    /**
     * Inefficient implementation, but easy to understand
     **/ 
    public static boolean calculateSlow(int []a, int []b){
      if(a.length==0 && b.length==0) return true;
      else if(a.length==0 || b.length==0) return false;
      else return a[0]==b[0]&&calculateSlow(getBiggerElements(a,a[0]),getBiggerElements(b,b[0]))&&calculateSlow(getSmallerElements(a,a[0]),getSmallerElements(b,b[0]));
    }
    private static int[] getBiggerElements(int []a,int n){
      int count=0;
      for(int e:a){
        if(e&gt;n) count++;
      }
      int []ret= new int[count];
      int i=0;
      for(int e:a){
        if(e&gt;n) ret[i++]=e;
      }
      return ret;
    }
    private static int[] getSmallerElements(int []a,int n){
      int count=0;
      for(int e:a){
        if(e&lt;n) count++;
      }
      int []ret= new int[count];
      int i=0;
      for(int e:a){
        if(e&lt;n) ret[i++]=e;
      }
      return ret;
    }
        boolean checkIfSameBSTs(ArrayList<Integer> listForTree1, ArrayList<Integer> listForTree2)
        {
            // both trees should have same size
            if (listForTree1.size() != listForTree2.size())
            {
                return false;
            }
             
            // if both trees are null trees
            if (listForTree1.size() == 0)
            {
                return true;
            }
             
            // root node has to be the same
            if (listForTree1.get(0) == listForTree2.get(0))
            {
                // segregate nodes for left and right sub-trees for both trees
                ArrayList<Integer> listForLeftTree1 = new ArrayList();
                ArrayList<Integer> listForRightTree1 = new ArrayList();
                 
                ArrayList<Integer> listForLeftTree2 = new ArrayList();
                ArrayList<Integer> listForRightTree2 = new ArrayList();
                 
                for (int i = 1; i < listForTree1.size(); i++)
                {
                    if (listForTree1.get(i) < listForTree1.get(0))
                    {
                        listForLeftTree1.add(listForTree1.get(i));
                    }
                    else
                    {
                        listForRightTree1.add(listForTree1.get(i));
                    }
                     
                    if (listForTree2.get(i) < listForTree2.get(0))
                    {
                        listForLeftTree2.add(listForTree2.get(i));
                    }
                    else
                    {
                        listForRightTree2.add(listForTree2.get(i));
                    }
                }
                 
                // and check that left and right sub-tree are also same
                return checkIfSameBSTs(listForLeftTree1, listForLeftTree2) &&
                       checkIfSameBSTs(listForRightTree1, listForRightTree2);
            }
             
            return false;
        }

    https://gist.github.com/KodeSeeker/9859330

    http://algorithms.tutorialhorizon.com/check-if-two-bsts-are-identical/
    public boolean identicalBSTs(Node rootA, Node rootB){
      if((rootA==null)&&(rootB==null)){
        return true;
      }else if((rootA!=null && rootB==null)||(rootA==null && rootB!=null)){
        return false;
      }else if(rootA.data==rootB.data){
        return identicalBSTs(rootA.left, rootB.left) && identicalBSTs(rootA.right, rootB.right);
      }else{
        return false;
      }
    }

    http://stackoverflow.com/questions/10951927/identical-bsts
    This answers the question as originally phrased, that is after identity of trees in the sense of same structure and elements.
    Comparing in-order (or any other) sequentialisation won't work: different trees have the same traversal. For example, the trees
    have the same in-order traversal a,b,c,d,e. You can use two (different) traversals and check whether they are the same, respectively.
    The classic solution, however, is a recursive algorithm:
      equal Leaf(x)       Leaf(y)       => x == y
    | equal Node(x,l1,r1) Node(y,l2,r2) => x == y && equal(l1,l2) && equal(r1,r2)
    | equal _             _             => false;
    
    It performs tree traversals on both trees simultaneously and takes time Θ(n), n the maximum of the respective number of nodes.


    Read full article from Check for Identical BSTs without building the trees | GeeksforGeeks

    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