diff --git a/DataStructures/Trees/BinaryTree.java b/DataStructures/Trees/BinaryTree.java index a9003d4b..0669f80f 100644 --- a/DataStructures/Trees/BinaryTree.java +++ b/DataStructures/Trees/BinaryTree.java @@ -22,7 +22,7 @@ public class BinaryTree { * * @author Unknown */ - class Node { + static class Node { /** Data for the node */ public int data; /** The Node to the left of this one */ @@ -53,6 +53,11 @@ public class BinaryTree { root = null; } + /** Parameterized Constructor */ + public BinaryTree(Node root) { + this.root = root; + } + /** * Method to find a Node with a certain value * diff --git a/DataStructures/Trees/CreateBinaryTreeFromInorderPreorder.java b/DataStructures/Trees/CreateBinaryTreeFromInorderPreorder.java new file mode 100644 index 00000000..ea9583bb --- /dev/null +++ b/DataStructures/Trees/CreateBinaryTreeFromInorderPreorder.java @@ -0,0 +1,95 @@ +package DataStructures.Trees; + +import java.util.HashMap; +import java.util.Map; +import DataStructures.Trees.BinaryTree.Node; + +/** + * Approach: Naive Solution: Create root node from first value present in + * preorder traversal. Look for the index of root node's value in inorder + * traversal. That will tell total nodes present in left subtree and right + * subtree. Based on that index create left and right subtree. + * Complexity: + * Time: O(n^2) for each node there is iteration to find index in inorder array + * Space: Stack size = O(height) = O(lg(n)) + * + * Optimized Solution: Instead of iterating over inorder array to find index of + * root value, create a hashmap and find out the index of root value. + * Complexity: + * Time: O(n) hashmap reduced iteration to find index in inorder array + * Space: O(n) space taken by hashmap + * + */ +public class CreateBinaryTreeFromInorderPreorder { + public static void main(String[] args) { + test(new Integer[] {}, new Integer[] {}); // empty tree + test(new Integer[] { 1 }, new Integer[] { 1 }); // single node tree + test(new Integer[] { 1, 2, 3, 4 }, new Integer[] { 1, 2, 3, 4 }); // right skewed tree + test(new Integer[] { 1, 2, 3, 4 }, new Integer[] { 4, 3, 2, 1 }); // left skewed tree + test(new Integer[] { 3, 9, 20, 15, 7 }, new Integer[] { 9, 3, 15, 20, 7 }); // normal tree + } + + private static void test(final Integer[] preorder, final Integer[] inorder) { + System.out.println("\n===================================================="); + System.out.println("Naive Solution..."); + BinaryTree root = new BinaryTree(createTree(preorder, inorder, 0, 0, inorder.length)); + System.out.println("Preorder Traversal: "); + root.preOrder(root.getRoot()); + System.out.println("\nInorder Traversal: "); + root.inOrder(root.getRoot()); + System.out.println("\nPostOrder Traversal: "); + root.postOrder(root.getRoot()); + + Map map = new HashMap<>(); + for (int i = 0; i < inorder.length; i++) { + map.put(inorder[i], i); + } + BinaryTree optimizedRoot = new BinaryTree(createTreeOptimized(preorder, inorder, 0, 0, inorder.length, map)); + System.out.println("\n\nOptimized solution..."); + System.out.println("Preorder Traversal: "); + optimizedRoot.preOrder(root.getRoot()); + System.out.println("\nInorder Traversal: "); + optimizedRoot.inOrder(root.getRoot()); + System.out.println("\nPostOrder Traversal: "); + optimizedRoot.postOrder(root.getRoot()); + } + + private static Node createTree(final Integer[] preorder, final Integer[] inorder, + final int preStart, final int inStart, final int size) { + if (size == 0) { + return null; + } + + Node root = new Node(preorder[preStart]); + int i = inStart; + while (preorder[preStart] != inorder[i]) { + i++; + } + int leftNodesCount = i - inStart; + int rightNodesCount = size - leftNodesCount - 1; + root.left = createTree(preorder, inorder, preStart + 1, inStart, leftNodesCount); + root.right = createTree(preorder, inorder, preStart + leftNodesCount + 1, i + 1, + rightNodesCount); + return root; + + } + + private static Node createTreeOptimized(final Integer[] preorder, final Integer[] inorder, + final int preStart, final int inStart, final int size, + final Map inorderMap) { + if (size == 0) { + return null; + } + + Node root = new Node(preorder[preStart]); + int i = inorderMap.get(preorder[preStart]); + int leftNodesCount = i - inStart; + int rightNodesCount = size - leftNodesCount - 1; + root.left = createTreeOptimized(preorder, inorder, preStart + 1, inStart, + leftNodesCount, inorderMap); + root.right = createTreeOptimized(preorder, inorder, preStart + leftNodesCount + 1, + i + 1, rightNodesCount, inorderMap); + return root; + } + +}