Binary tree Inorder traversal from only postorder traversal provided - algorithm

I got a question in my coding challenge.
A complete binary tree is a binary tree where every node except the leaf node has two child nodes and the last level of the tree for an edge-height h has 2^h leaf-nodes.
Your task is simple, given the post-order traversal for a complete binary tree, print its in-order traversal.
The elements in the binary tree are of type character i.e. each node stores one character value.
Format of input / output
Input Format:
Only one string input denoting the postorder traversal.
Constraints:
1 <= input.length <= 1000
Output Format:
output one string that denotes the inorder traversal of the binary tree
Sample
Sample Input 0:
BCA
Sample Output 0:
BAC

I did have a full answer ready to go, but #EricWang beat me to the implementation. So here's a supplementary answer describing the process in more detail. Please accept his as the answer.
I'm going to use the post-order traversal DEBFGCA, as it's useful to consider slightly more nodes.
Because the tree is complete, for any given node we know that the the number of children on the left is the same as the number of children on the right. Therefore we can look at the post-order traversal DEBFGCA and know that it has the structure LLLRRRN, where L is the post-order traversal of the left subtree, R is the post-order traversal of the right subtree, and N is the node itself.
More generally, we know that the post-order traversal of the left subtree is characters 0 to (tree.length - 1)/2 - 1, and the post-order traversal of the right subtree is characters (tree.length -1)/2 - 1 to tree.length - 2. The node is the last character, at tree.length - 1.
Obviously, to change this to an in-order traversal, we just have to identify the left and right subtrees, change them to in-order traversal, and then return LLLNRRR. We can use recursion to convert the left and right subtrees to in-order.
So for example, start with DEBFGCA. We know the structure is LLLRRRN, so the left subtree is DEB, the right subtree is FGC, and the node is A. We want to turn DEB into in-order...
Process DEB. We know the left subtree is D, right is E, node is B. Both subtrees have length 1, so are leaves. No further recursion required. Return LNR, which is DBE.
Process FGC. As before, return FCG.
Now we know the in-order left is DBE and right is FCG. Return LLLNRRR, which is DBEAFCG.

You can do it dynamically, with recursion.
Mechanism
Split a tree to 3 parts: left, right, root.
Re-join them in order: left, root, right.
Split recursively, till the length of subtree is one.
Code - in Java
PostToInOrder.java
public class PostToInOrder {
public static String convert(String post) {
checkPerfect(post); // check whether tree is perfect,
return convertInner(post);
}
private static String convertInner(String post) {
int len = post.length();
if (len == 1) return post; // base case,
String left = post.substring(0, len >> 1); // left of post,
String right = post.substring(len >> 1, len - 1); // right of post,
char root = post.charAt(len - 1); // root of post,
return convertInner(left) + root + convertInner(right);
}
private static void checkPerfect(String tree) {
if (!isPerfect(tree)) throw new IllegalArgumentException("input is not perfect tree, size: " + tree.length());
}
private static boolean isPerfect(String tree) {
int len = tree.length();
if (len < 1) return false;
while (len != 0) {
if ((len & 1) == 0) return false;
len >>= 1;
}
return true;
}
}
PostToInOrderTest.java:
(Unit test, via TestNG)
import org.testng.Assert;
import org.testng.annotations.Test;
public class PostToInOrderTest {
#Test
public void test() {
Assert.assertEquals(PostToInOrder.convert("BCA"), "BAC");
Assert.assertEquals(PostToInOrder.convert("02146538A9CEDB7"), "0123456789ABCDE");
Assert.assertEquals(PostToInOrder.convert("A"), "A"); // single element,
}
#Test(expectedExceptions = IllegalArgumentException.class)
public void test_invalid_empty() {
PostToInOrder.convert("");
}
#Test(expectedExceptions = IllegalArgumentException.class)
public void test_invalid_notPerfect() {
PostToInOrder.convert("AB");
}
}
BTW:
The tree described in question is a perfect binary tree.
It's a sub type of complete binary tree.
A complete tree is not necessary perfect, its last level could lack of some leaves.
e.g AB is a complete tree, but not perfect tree.

Related

How do i calculate space complexity for checking if binary search tree is balanced?

I want to check if binary search tree provided to me is balanced or not.
Since tree already exists in memory, there is no additional storage needed while checking if tree is balanced when traversing through nodes.
So I assume space complexity would be O(1).
Is it correct?
// Definition for binary tree
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
public class Solution {
public boolean isBalanced(TreeNode root) {
if (root == null)
return true;
if (getHeight(root) == -1)
return false;
return true;
}
public int getHeight(TreeNode root) {
if (root == null)
return 0;
int left = getHeight(root.left);
int right = getHeight(root.right);
if (left == -1 || right == -1)
return -1;
if (Math.abs(left - right) > 1) {
return -1;
}
return Math.max(left, right) + 1;
}
}
Your algorithm is O(height) space, not O(1) - you need to store 1 recursive function call in memory for every node as you recurse down the tree, and you can never go deeper than O(height) in the tree (before you return and can get rid of the already-fully-processed nodes).
For a tree like:
(Image reference - Wikipedia)
Your calls will go like this:
getHeight(8)
getHeight(3)
getHeight(1)
getHeight(6)
getHeight(4)
getHeight(7)
getHeight(10)
getHeight(14)
getHeight(13)
Here, getHeight(8) calls getHeight(3), which calls getHeight(1) and getHeight(6), etc.
After we've finished calling the function for 1 (returning the result to the call for 3), we don't need to keep that in memory any more, thus the maximum number of calls that we keep in memory is equal to the height of the tree.
It can be done in O(1) space, but it's fairly complicated and really slow (much slower than the O(n) that your solution takes).
The key is that we have a binary search tree, so, given a node, we'd know whether that node is in the left or right subtree of any ancestor node, which we can use to determine the parent of a node.
I may create a separate Q&A going into a bit more details at some point.

Rebalancing an arbitrary BST?

Reference:
I was asked this question #MS SDE interview, 3rd round. And it's not a homework problem. I also gave it a thought and mentioning my approach below.
Question:
Modify a BST so that it becomes as balanced as possible. Needless to mention, you should do it as efficient as possible.
Hint:
Interviewer said that this is a logical question, if you think differently you will get the answer. No difficult coding involved.
--> Having said that, I do not think he was expecting me to point to AVL/RB Trees.
My Solution:
I proposed that, I would do inorder traversal of tree, take middle element as root of new tree(lets call it new root). Then go to the left part of middle element, take its middle element as root of left subtree of tree rooted new root. Similarly do for right part.
Doing this recursively will give the optimal balanced BST.
Why I am posting it here:
But he was not satisfied with the answer :( So, is there really a way of doing this w/o going for weights/RB coloring strategy, or was he just fooling around with me?
Please put in your expert thoughts.
Duplicate? No!
I know there is this question but the solution proposed by requester is too complicated, and other one talks about AVL trees.
You might want to look into the Day-Stout-Warren algorithm, which is an O(n)-time, O(1)-space algorithm for reshaping an arbitrary binary search tree into a complete binary tree. Intuitively, the algorithm works as follows:
Using tree rotations, convert the tree into a degenerate linked list.
By applying selective rotations to the linked list, convert the list back into a completely balanced tree.
The beauty of this algorithm is that it runs in linear time and requires only constant memory overhead; in fact, it just reshapes the underlying tree, rather than creating a new tree and copying over the old data. It is also relatively simple to code up.
Hope this helps!
"Balanced as possible" = complete (or full) binary tree1. You cannot get more balanced that it.
The solution is simple - build an "empty" complete binary tree, and iterate the new tree and the input tree (simultaneously) in inorder-traversal to fill the complete tree.
When you are done, you have the most balanced tree you can get, and time complexity of this approach is O(n).
EDIT:
This should be done following these steps:
Build a dummy complete tree with n nodes. All the values to each
node will be initialized to some garbage value.
Create two iterators: (1) originalIter for the original tree, (2) newIter for the new (initialized with garbage) tree. Both iterators will return elements in in-order traversal.
Do the following to fill the tree with the values from the original:
while (originalIter.hasNext()):
newIter.next().value = originalIter.next().value
(1) (From Wikipedia): A complete binary tree is a binary tree in which every level, except possibly the last, is completely filled, and all nodes are as far left as possible
The DSW algorithm can solve this is O(n) time. The algorithm goes as follows:
1] Using right-rotation operations, turn the tree into a linked list
(a.k.a. backbone or vine)
2] Rotate every second node of the backbone about its parent to turn
the backbone into a perfectly balanced BST.
Reference
This will convert your normal BST into a balanced BST with minimum possible height in O(n). First, save all your nodes sorted into a vector. Then, the root is the mid element and recursively build a tree from 0 to mid-1 as its left and build a tree from mid+1 to vector.size()-1 as its right child. After all these steps root keeps the balanced BST with the min-height.
import java.util.Vector;
public class ConvertBSTIntoBalanced {
public static void main(String[] args) {
TreeNode node1 = new TreeNode(1);
TreeNode node2 = new TreeNode(2);
TreeNode node3 = new TreeNode(3);
TreeNode node4 = new TreeNode(4);
node1.right = node2;
node2.right = node3;
node3.right = node4;
ConvertBSTIntoBalanced convertBSTIntoBalanced = new ConvertBSTIntoBalanced();
TreeNode balancedBSTRoot = convertBSTIntoBalanced.balanceBST(node1);
}
private void saveNodes(TreeNode node, Vector<TreeNode> nodes) {
if (node == null)
return;
saveNodes(node.left, nodes);
nodes.add(node);
saveNodes(node.right, nodes);
}
private TreeNode buildTree(Vector<TreeNode> nodes, int start, int end) {
if (start > end)
return null;
int mid = (start + end) / 2;
TreeNode midNode = nodes.get(mid);
midNode.left = buildTree(nodes, start, mid - 1);
midNode.right = buildTree(nodes, mid + 1, end);
return midNode;
}
public TreeNode balanceBST(TreeNode root) {
Vector<TreeNode> nodes = new Vector<>();
saveNodes(root, nodes);
return buildTree(nodes, 0, nodes.size() - 1);
}
public class TreeNode {
public Integer val;
public TreeNode left;
public TreeNode right;
public TreeNode(Integer x) {
val = x;
}
}
}
I hope it helps.

How to verify if a given tree is a Binary Search Tree or not [duplicate]

This question already has answers here:
How do you validate a binary search tree?
(33 answers)
Closed 8 years ago.
I wanted to know if a given binary tree is a binary search tree or not.
I don't know How to do that?
The only thing I know is that the inorder traversal of BST will gives you ascending order output.
So, is this the only condition we need to verify or is there anything else we are suppose to check.
In case if there are some other necessary conditions to be checked, What are they? and why those conditions are necessary to be checked? Because, I think, INORDER traversal itself can tell you easily if the given tree is BST or not.
Yes, if inorder traversal of the tree gives you a strictly monotonic list of values that is sufficient to determine that the tree is a BST.
By definition of Binary search tree, if every node of the binary tree satisfy the following conditions then it is a Binary Search Tree:
The left subtree of a node should contain only nodes with keys less than the node’s key
The right subtree of a node should contain only nodes with keys greater than the node’s key
Both the left and right subtrees must also be binary search trees.
All the above conditions are verified if the inorder traversal is in ascending order.
Actually - it is not enough to just do an in order traversal - you also need to verify that each node's value follows the rules of the tree. In the case of a BST, the left child value is less than the node value and the right child value is greater than the node value. Here is a recursive example in Java.
private static boolean isBST(Node current, Comparable more, Comparable less) {
if (current == null)
return true;
if (less != null && current.value.compareTo(less) > 0)
return false;
if (more != null && current.value.compareTo(more) < 0)
return false;
return isBST(current.left, more, current.value) &&
isBST(current.right, current.value, less);
}
public static boolean isBST(BinarySearchTree tree) {
return isBST(tree.getRoot(), null, null);
}
While doing In-Order traversal, we can keep track of previously visited node
Code:
bool isBST(struct node* root)
{
static struct node *prev = NULL;
// traverse the tree in inorder fashion and keep track of prev node
if (root)
{
if (!isBST(root->left))
return false;
// Allows only distinct valued nodes
if (prev != NULL && root->data <= prev->data)
return false;
prev = root;
return isBST(root->right);
}
return true;
}
A simple but elegant recursive solution in Java:
public static boolean isBST(TreeNode node, int leftData, int rightData)
{
if (node == null) return true;
if (node.getData() > leftData || node.getData() <= rightData) return false;
return (isBST(node.left, node.getData(), rightData)
&& isBST(node.right, leftData, node.getData()));
}
The initial call to this function can be something like this:
if (isBST(root, Integer.MAX_VALUE, Integer.MIN_VALUE))
System.out.println("This is a BST.");
else
System.out.println("This is NOT a BST!");
Essentially we keep creating a valid range (starting from [ MIN_VALUE, MAX_VALUE]) and keep shrinking it down foe each node as we go down recursively.
Source: http://exceptional-code.blogspot.com/2011/08/binary-search-trees-primer.html

binary tree with special property

There is binary tree with special property that all its inner node have val = 'N' and all leaves have val = 'L'. Given its preorder. construct the tree and return the root node.
every node can either have two children or no child
Recursion is your friend.
Tree TreeFromPreOrder(Stream t) {
switch (t.GetNext()) {
case Leaf: return new LeafNode;
case InternalNode:
Node n = new Node;
n.Left = TreeFromPreOrder(t);
n.Right = TreeFromPreOrder(t);
return n;
default:
throw BadPreOrderException;
}
}
Looking at it as a recursive method, it becomes easy to see how do other things.
For instance, say we wanted to print the InOrder traversal. The code will look something like this:
void PrintInorderFromPreOrder(Stream t) {
Node n = new Node(t.GetNext());
switch (n.Type) {
case Leaf: return;
case InternalNode:
PrintInorderFromPreOrder(t);
print(n.Value);
PrintInorderFromPreOrder(t);
default:
throw BadPreOrderException;
}
}
Also, I would like to mention that this is not that artificial. This type of representation can actually be used to save space when we need to serialize a binary tree: Efficient Array Storage for Binary Tree.
Just the basic idea: keep a stack where the head is the "current" node and read sequentially the string representing the preorder.
Now, if you encounter a 'L', then it means the "current" node has as a child a leaf, so you can "switch" to the right child and resuming building the corresponding subtree, pushing the root of that subtree; if, when encountering a 'L', the "current node" has already two children, pop an element from the stack.

Inorder tree traversal: Which definition is correct?

I have the following text from an academic course I took a while ago about inorder traversal (they also call it pancaking) of a binary tree (not BST):
Inorder tree traversal
Draw a line around the outside of the
tree. Start to the left of the root,
and go around the outside of the tree,
to end up to the right of the root.
Stay as close to the tree as possible,
but do not cross the tree. (Think of
the tree — its branches and nodes — as
a solid barrier.) The order of the
nodes is the order in which this line
passes underneath them. If you are
unsure as to when you go “underneath”
a node, remember that a node “to the
left” always comes first.
Here's the example used (slightly different tree from below)
However when I do a search on google, I get a conflicting definition. For example the wikipedia example:
Inorder traversal sequence: A, B, C,
D, E, F, G, H, I
(leftchild,rootnode,right node)
But according to (my understanding of) definition #1, this should be
A, B, D, C, E, F, G, I, H
Can anyone clarify which definition is correct? They might be both describing different traversal methods, but happen to be using the same name. I'm having trouble believing the peer-reviewed academic text is wrong, but can't be certain.
In my bad attempt at the drawing here's the order that shows how they should be picked.
pretty much pick the node that is directly above the line being drawn,.
Forget the definitions, it's so much easier to just apply the algorithm:
void inOrderPrint(Node root)
{
if (root.left != null) inOrderPrint(root.left);
print(root.name);
if (root.right != null) inOrderPrint(root.right);
}
It's just three lines. Rearrange the order for pre- and post- order.
If you read carefully you see that the first "definition" says to start left of the root and that the order of the nodes is determined by when you pass under them. So B is not the first node, as you pass it from the left on the way to A, then first pass under A after which you go up and pass under B. Therefore it seems that both definitions give the same result.
I personally found this lecture quite helpful.
Both definitions give the same result. Don't be fooled by the letters in the first example - look at the numbers along the path. The second example does use letters to denote the path - perhaps that is what is throwing you off.
For example, in your example order showing how you thought the second tree would be traversed using the algorithm of the first one, you place "D" after "B" but you shouldn't because there is still a left-hand child node of D available (that's why the first item says "the order in which this line passes underneath them."
this may be late but it could be useful for anyone later ..
u just need not to ignore the dummy or null nodes e.g the Node G has a left null node .. considering this null node will make every thing alright ..
The proper traversal would be: as far left as possible with leaf nodes (not root nodes)
Left Root Right
A B NULL
C D E
Null F G
H I NULL
F is root or left, i am not sure
I think the first binary tree with the root of a is a Binary tree which is not correctly constructed.
Try to implement so that all the left side of the tree is less than the root and all the right side of the tree is greater than or equal to the root.
But according to (my understanding of)
definition #1, this should be
A, B, D, C, E, F, G, I, H
Unfortunately, your understanding is wrong.
Whenever you arrive at a node, you must descend to an available left node, before you look at the current node, then you look at an available right node.
When you chose D before C, you didn't descend to the left node first.
Hey according to me as mentioned in wiki is correct the sequence for a inorder traversal is left-root-right.
Till A, B, C, D, E, F i think you have understood already. Now after root F the next node is G that doesn't hav a left node but a right node so as per the rule (left-root-right) its null-g-right. Now I is the right node of G but I has a left node hence the traversal would be GHI. This is correct.
Hope this helps.
For an inline tree traversal you have to keep in mind that the order of traversal is left-node-right. For the above diagram that you are conflicted on, your error occurs when you read a parent node before reading any leaf(children) nodes to the left.
The proper traversal would be: as far left as possible with leaf nodes(A), return to parent node(B), move to the right, but since D has a child to its left you move down again(C), back up to C's parent(D), to D's right child(E), reverse back to the root(F), move to the right leaf(G), move to G's leaf but since it has a left leaf node move there(H), return to parent(I).
the above traversal reads the node when I have it listed in parenthesis.
package datastructure;
public class BinaryTreeTraversal {
public static Node<Integer> node;
public static Node<Integer> sortedArrayToBST(int arr[], int start, int end) {
if (start > end)
return null;
int mid = start + (end - start) / 2;
Node<Integer> node = new Node<Integer>();
node.setValue(arr[mid]);
node.left = sortedArrayToBST(arr, start, mid - 1);
node.right = sortedArrayToBST(arr, mid + 1, end);
return node;
}
public static void main(String[] args) {
int[] test = new int[] { 1, 2, 3, 4, 5, 6, 7 };
Node<Integer> node = sortedArrayToBST(test, 0, test.length - 1);
System.out.println("preOrderTraversal >> ");
preOrderTraversal(node);
System.out.println("");
System.out.println("inOrderTraversal >> ");
inOrderTraversal(node);
System.out.println("");
System.out.println("postOrderTraversal >> ");
postOrderTraversal(node);
}
public static void preOrderTraversal(Node<Integer> node) {
if (node != null) {
System.out.print(" " + node.toString());
preOrderTraversal(node.left);
preOrderTraversal(node.right);
}
}
public static void inOrderTraversal(Node<Integer> node) {
if (node != null) {
inOrderTraversal(node.left);
System.out.print(" " + node.toString());
inOrderTraversal(node.right);
}
}
public static void postOrderTraversal(Node<Integer> node) {
if (node != null) {
postOrderTraversal(node.left);
postOrderTraversal(node.right);
System.out.print(" " + node.toString());
}
}
}
package datastructure;
public class Node {
E value = null;
Node<E> left;
Node<E> right;
public E getValue() {
return value;
}
public void setValue(E value) {
this.value = value;
}
public Node<E> getLeft() {
return left;
}
public void setLeft(Node<E> left) {
this.left = left;
}
public Node<E> getRight() {
return right;
}
public void setRight(Node<E> right) {
this.right = right;
}
#Override
public String toString() {
return " " +value;
}
}
preOrderTraversal >>
4 2 1 3 6 5 7
inOrderTraversal >>
1 2 3 4 5 6 7
postOrderTraversal >>
1 3 2 5 7 6 4
void
inorder (NODE root)
{
if (root != NULL)
{
inorder (root->llink);
printf ("%d\t", root->info);
inorder (root->rlink);
}
}
This the most simplest approach to recursive definition of in-order traversal, just call this function in the main function to get the in-order traversal of a given binary tree.
It is correct for preorder,nt for inorder

Resources