BST to LinkList and back to same BST - algorithm

Since I could not find anything useful so I am here to ask my question:
How can we convert the BST to a In-order linklist, and back to "same" BST, without using any extra space.
What I have tried so far (still doing though): I tried Morris Traversal to link up to the next in-order successor,
but it is not able to connect for all the nodes, only working for the left subtree, and right subtree, not for the actual root of the tree.
Please suggest how can I convert Tree to Linked List and back to Same tree...

To store a tree in lists - you need at least two lists: one for pre-order traversal, and the other for in-order traversal.
Luckily - since the tree is a BST, the in-order traversal is just the sorted list.
So, you can store the pre-order traversal (You can try doing it in-place) and by sorting the elements in re-construction, you can get the in-order traversal.
This post discusses how to reconstruct a tree from the inorder and pre-order traversals of it.

Binary Search Tree to List:
subTreeToList(node)
if (node.hasLeft()) then subTreeToList(node.left, list)
list.add(node.Value)
if (node.hasRight()) subTreeToList(node.right, list)
end if
subTreeToList end
treeToList(tree)
subTreeToList(tree.root)
treeToList end
list <- new List()
treeToList(tree)
You need to implement the idea above into your solution, if you are working with object-oriented technologies, then list and trees should be data members, otherwise they should be passed to the functions as references.
You can build back your tree knowing that insertion in the tree looks like this:
Insert(tree, value)
if (tree.root is null) then
tree.createRoot(value)
else
node <- tree.root
while (((node.value < value) and (node.hasRight())) or ((node.value > value) and (node.hasLeft())))
if ((node.value < value) and (node.hasRight())) then node <- node.right()
else node <- node.left()
end if
while end
if (node.value > value) then node.createLeft(value)
else node.createRight(value)
end if
end if
insert end
You just have to traverse your list sequentially and call the function implemented based on my pseudo-code above. Good luck with your homework.

I think I found the solution myself: below is the complete Java implementation
The logic + pseudo Code is as below
[1] Find the left most node in the tree, that will be the head of the LinkList, store it in the class
Node HeadOfList = null;
findTheHeadOfInorderList (Node root)
{
Node curr = root;
while(curr.left != null)
curr = curr.left;
HeadOfList = curr; // Curr will hold the head of the list
}
[2] Do the reverse - inorder traversal of the tree to convert it to a LL on right pointer, and make sure the left pointer is always pointing to the parent of the node.
updateInorderSuccessor(Node root, Node inorderNext, Node parent)
{
if(root != null)
//Recursively call with the right child
updateInorderSuccessor(root.right, inorderNext, root);
// Update the in-order successor in right pointer
root.right = inorderNext;
inorderNext = root;
//Recursively call with the left child
updateInorderSuccessor(root.left, inorderNext, root);
// Update the parent in left pointer
root.left = parent;
}
}
[3] To convert it back :
Traverse the list and find the node with left pointer as null,
Make it the root, break the link of this root in the linklist and also from its children...
Now the link list is broken into two parts one for left Subtree and one for right subtree,
recursively find the roots in these two list and make them the left and right child, Please refer the function restoreBST()
Node restoreBST(Node head)
{
if(head == null || (head.left == null && head.right == null)) return root;
Node prev, root, right, curr;
curr = head;
// Traverse the list and find the node with left as null
while(curr != null)
{
if(curr.left == null)
{
// Found the root of this tree
root = curr;
// Save the head of the right list
right = curr.right;
// Detach the children of the root just found, these will be updated later as a part of the recursive solution
detachChildren(curr, head);
break;
}
prev = curr;
curr = curr.right;
}
// By now the root is found and the children of the root are detached from it.
// Now disconnect the right pointer based connection in the list for the root node, so that list is broken in to two list, one for left subtree and one for right subtree
prev.right = null;
root.right = null;
// Recursively call for left and right subtree
root.left = restoreBST(head);
root.right = restoreBST(right);
//now root points to its proper children, lets return the root
return root;
}
Logic to detach the children is simple : Iterate through the list and look for the nodes with left pointer equal to root.
private void detachChildren(AvlNode root, AvlNode head) {
AvlNode curr = head;
while(curr != null)
{
if(curr.left == root)
{
curr.left = null;
}
curr = curr.right;
}
}

Here is a recursive solution for BST to LL, hope you find it useful.
Node BSTtoLL(BST root) {
if(null == root) return null;
Node l = BSTtoLL(root.left);
Node r = BSTtoLL(root.right);
Node l1 = null;
if(null != l) {
l1 = l;
while(null != l.left) { l = l.left; }
l.left = root;
l.right = null;
}
if(null != r) {
root.left = r;
root.right = null;
}
if(null != l1) return l1;
return root;
}

Related

Why do I need to push the right node before the left node during iterative solution to pre-order traversal when it's supposed to be left before right?

To solve this leetcode question :
Binary tree pre order traversal
It is good to remember that pre-order traversal traverses a tree in the order of
root->left->right.
In light of this, if I write an iterative solution to the problem above following the order of insertion of root, left and right, my solution does not pass all the hidden test cases.
To understand this, below is the code that does not pass all the hidden test cases:
public List<Integer> preorderTraversal(TreeNode root) {
//preOrder means root comes before other traversals therefore root,left,right
List<Integer> finalListToReturn = new ArrayList();
if(root == null)
return finalListToReturn;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root); //add root first
while(!stack.isEmpty()){
TreeNode node = stack.pop();
finalListToReturn.add(node.val); //add to list
//left must be traversed before the right,this is the natural order for preOrder
if(node.left != null)
stack.push(node.left);
if(node.right != null)
stack.push(node.right);
}
return finalListToReturn;
}
but the above code will not pass all hidden testcases when I submit.
However, if i traverse right node before left, all testcases pass, why is that so ?
For context,this is the snippet that passes all hidden test cases when submited.
public List<Integer> preorderTraversal(TreeNode root) {
//preOrder means root comes before other traversals therefore root,left,right
List<Integer> finalListToReturn = new ArrayList();
if(root == null)
return finalListToReturn;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root); //add root first
while(!stack.isEmpty()){
TreeNode node = stack.pop();
finalListToReturn.add(node.val); //add to list
//once right is traversed first before left, then every test case passes,why is that so?
if(node.right != null)
stack.push(node.right);
if(node.left != null)
stack.push(node.left);
}
return finalListToReturn;
}
Why is it that the first code snippet which traverses a binary search tree in the right pre-order route(root->left->right) rather does not pass all test cases but when the same code is tweaked to traverse in the order of (root->right->left) in the second snippet,all test cases pass? Can someone explain why?
So basically, if you look carefully, we are using a stack.
Observe the while loop we are using critically and you'll realize that we do pop(ie return the item at the top), and in this case, a Stack follows the LIFO principle, that is , the last element in,becomes the first element to come out during a pop.
Now after we add our node.val to finalListToReturn inside the while loop, if we add the left element first and then push the right element, what it means is that , during the next iteration, the last element that entered, the right element, will be popped first since a stack follows LIFO.
Obviously, we don't want that, so we will rather push the right element first and then the left element. Now during the next pop, the left element will pop first before the right, which is what we were looking for originally.
Thus, our final code should be exactly like the second snippet above:
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> finalListToReturn = new ArrayList();
if(root == null)
return finalListToReturn;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.pop();
finalListToReturn.add(node.val);
if(node.right != null)
stack.push(node.right);
if(node.left != null)
stack.push(node.left);
}
return finalListToReturn;
}

What algorithm is this code using to find the lowest common ancestor of a binary tree?

I found this solution on Leetcode while trying to solve this problem:
https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/
Everyone on Leetcode seems to take for granted how this works. But I don't get it. What is going on here and what algorithm is this using to find the LCA of the binary tree?
public TreeNode lowestCommonAncestorBinaryTree(TreeNode root, TreeNode p, TreeNode q) {
if(root==null) {
return null;
}
if(root==p) {
return p;
}
if(root==q) {
return q;
}
TreeNode left = lowestCommonAncestorBinaryTree(root.left, p, q);
TreeNode right = lowestCommonAncestorBinaryTree(root.right, p, q);
if (left != null && right != null) {
return root;
}
if(left!=null && right==null) {
return left;
}
if(right!=null && left==null) {
return right;
}
return null;
}
Quite simple:
The code looks at the root of the tree. If the root is p or q, then it returns it.
If it's not in the root, it searches in the left and right subtrees of the root, repeating the process until root is actually p or q.
Then comes the 3 last ifs.
if (left != null && right != null) return root;
This means that it found one of the nodes in the left subtree of the root and another in the right subtree of the root, hence root is the LCA.
if(left != null && right == null) return left;
This means that it found a node in the left subtree but no node in the right subtree, then the left node is the parent of the other node, hence the LCA.
if(right != null && left == null) return right;
This means that it found a node in the right subtree but no node in the left subtree, then the right node is the parent of the other node, hence the LCA.
Otherwise, the nodes aren't in the tree and there's no LCA.

is wikipedia iterative postorder tree traversal pseudo code wrong?

Here is the pseudo code that wikipedia gives for iterative postorder tree traversal.
iterativePostorder(node)
parentStack = empty stack
lastnodevisited = null
while (not parentStack.isEmpty() or node ≠ null)
if (node ≠ null)
parentStack.push(node)
node = node.left
else
peeknode = parentStack.peek()
if (peeknode.right ≠ null and lastnodevisited ≠ peeknode.right)
/* if right child exists AND traversing node from left child, move right */
node = peeknode.right
else
visit(peeknode)
lastnodevisited = parentStack.pop()
It is pretty straight forward, and I have implemented it in Java. But it does not work, the problem is that every time it visits the most left leaf and return to its parent, it will add that left leaf again into the stack in next iteration. This causes an infinite loop. Is my method incorrect or the wikipedia version is wrong?
public static List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) return res;
Stack<TreeNode> s = new Stack<TreeNode>();
TreeNode lastVisitedNode = null;
TreeNode curr = root;
int i = 0;
while (curr != null || !s.isEmpty()) {
if (curr != null) {
System.out.println("push " + curr.val);
s.push(curr);
curr = curr.left;
} else {
curr = s.peek();
if (curr.right != null && lastVisitedNode != curr.right) {
curr = curr.right;
} else {
res.add(curr.val);
System.out.println("pop " + curr.val);
lastVisitedNode = s.pop();
}
}
System.out.println(s);
System.out.println(res);
if (i>8) break;
else i++;
}
return res;
}
The wikipedia version is wrong for the exact same reason as you've explained it.
Here is a probably better pseudo-code, from geeksforgeeks
1.1 Create an empty stack
2.1 Do following while root is not NULL
a) Push root's right child and then root to stack.
b) Set root as root's left child.
2.2 Pop an item from stack and set it as root.
a) If the popped item has a right child and the right child
is at top of stack, then remove the right child from stack,
push the root back and set root as root's right child.
b) Else print root's data and set root as NULL.
2.3 Repeat steps 2.1 and 2.2 while stack is not empty.
You will have to add extra code to check if the node right child is null in 2.1.a though.
The wikipedia pseudocode is not wrong. They use two different variables: node and peekNode, while you only use curr for both. Node == null refers to the case when there is no more of a left branch left to explore, so we can stop pushing and instead investigate the next element in the stack. You can either revert to using two different variables, or you make the following fix in your code:
Since you reassign curr to a non-null value everytime you investigate the stack, you need to reset curr to null after you visit your node. (Because the state that still no more left branch left to explore is still unchanged).
The wikipedia pseudocode doesn't have to do this because their node value remains null.
Here is my code which gives a perfect answer:
var currentNode = this.root()
var previousNode = null
while(!nodeStack.isEmpty() || currentNode) {
// If there is a node on which the recursive call is made, we have a subtree to explore. If this is null, we have to backtrack and do a callback.
if (currentNode) {
nodeStack.push(currentNode)
previousNode = currentNode
currentNode = currentNode.leftChild
} else {
currentNode = nodeStack.peek()
if (currentNode.rightChild && previousNode != currentNode.rightChild) {
currentNode = currentNode.rightChild
} else {
callback(currentNode)
currentNode = null
previousNode = nodeStack.pop()
}
}
}

How binary search tree is created?

Suppose i am having an array say
1 5 4 6 8 9 10 22 17 7 9 3
I want to create a binary search tree from this array. I need algorithm to understand that.
I have read rest other things related to BST like inorder traversal preorder postorder, tree walk, insertion deletion etc
Book has not provided how to create BST. Need help here
if you do not care about the tree being balanced it is simple:
put the first element of the tree as the head.
iterate over the array. if an element is bigger than the node take a left(repeat the step for the left child) otherwise take a right(repeat the step for the right child).
if the left/right child is a null insert your new value there.
guaranteed to produce a binary search tree - just not a balanced one.
Firstly, you should choose a root node for your BST. Once you have chosen a root node, it is already easy to construct a BST taking into consideration the fact that: left children are less than the parent node and all right children are greater than the parent node.
private Node root;
public void insert(int val) {
if (root == null) {
root = new Node(val);
} else {
insertHelper(root, val);
}
}
private void insertHelper(Node node, int val) {
if (val < node.val) {
if (node.left == null) {
node.left = new Node(val);
} else {
insertHelper(node.left, val);
}
} else if (node.val < val) {
if (node.right == null) {
node.right = new Node(val);
} else {
insertHelper(node.right, val);
}
}
}
If the given array is sorted, you can do the following:
Take the middle element of the array and make it the root of the tree
Take the left sub-array and make it the left sub-tree of the root recursively
Take the right sub-array and make it the right sub-tree of the root recursively
Otherwise you can always sort the array before applying the procedure
struct node* construct(int arr[], int start, int end)
{
if(start>end)
return;
else if (start==end)
{
/*assuming we have a function newNode(int) which creates a new BST Node*/
node* Node = newNode(arr[start]);
return Node;
}
int mid = (start+end)/2;
node* root = newNode(arr[mid]);
root->left = construct(arr,start,mid-1);
root->right = construct(arr,mid+1,end);
return root;
}

Traversing two trees together?

I am looking a lot of interview problems where the question requires traversing two trees together, I am not sure exactly how to go about doing this.
e.g.
Given references to roots of two binary trees, how do you determine
whether the sequence of the leaf elements equal but you must
implement short circuiting return when the first node violates the
rule.
Is your question asking to find out whether:
"the sequence created by visiting all the leaf nodes of 2 trees is same"
with a constraint that when found a mismatch of leaf values, then we must quit immediately.
If so, I propose following solution:
insert (root of tree1) in stack1
insert (root of tree2) in stack2
temp1 = (root of tree1) -> left child
temp2 = (root of tree2) -> left child
while(stack1 and stack2 arent empty)
{
found = false
while(found == false) {
if (temp1 is leaf node)
child1 = value of temp1
found = true
pop element from stack1
set temp1 to its right child
if (temp1 has left child)
put temp1 in stack1
set temp1 to its left child
}
found = false
while(found == false) {
if (temp2 is leaf node)
child2 = value of temp2
found = true
pop element from stack2
set temp2 to its right child
if (temp2 has left child)
put temp2 in stack2
set temp2 to its left child
}
if(child1 != child2)
return
}
One possible solution:
I have created a tree class which has a method GetNextLeafNode(). This is responsible for returning the next immediate leaf node of a tree.
With the tree class I am keeping a stack to maintain the traversed elements
In the GetNextLeafNode() method, I am doing iterative tree traversal (Pre order).
Whenever I encounter a node(stack.Pop()) which is leaf I am just returning it. Otherwise I am pushing left and right pointers to the stack. Initially root node is pushed. At any time state of stack is proper.
Here is the code in C#:
public TreeNode GetNextLeafNode()
{
TreeNode leaf = null;
while (s.Count != 0)
{
TreeNode n = s.Pop();
if ((n.Left == null) && (n.Right == null))
{
leaf = n;
return leaf;
}
else
{
if (n.Right != null)
s.Push(n.Right);
if (n.Left != null)
s.Push(n.Left);
}
}
return leaf;
}
Now, we can create two different trees say, t1 and t2.
We can do the comparision as follows:
int data1 = t1.GetNextLeafNode().Data;
int data2 = t2.GetNextLeafNode().Data;
while (data1 == data2)
{
//both the leaf nodes are same.
data1 = t1.GetNextLeafNode().Data;
data2 = t2.GetNextLeafNode().Data;
}
In pseudo-code:
Go down to the first leaf (let's say left-most) in each tree.
Compare.
If not equal RETURN error.
Step to the next leaf in each tree (intuitively -- go up until you see a way to step to the right child, then take only left children on your way till you reach a leaf).
If one of the trees has a leaf but another returned to root RETURN error.
If both trees returned to root RETURN success.
Go to step 2.
A simple python solution.
Though this is not space optimal as we are storing leaves that can be O(N+M). This is not iterating both the trees together.
Time complexity - O(N+M).
You can also think of a solution where space is O(max(N,M)) in a similar fashion.
def binaryTreeLeafs(root1, root2):
# The order in which we see leaves will
# be maintained as it is inorder traversal.
def dfs(node, leaves):
if not node:
return
if not node.left and not node.right:
leaves.append(node.val)
return
dfs(node.left, leaves)
dfs(node.right, leaves)
leaves1 = []
leaves2 = []
dfs(root1, leaves1)
dfs(root2, leaves2)
return leaves1 == leaves2
# O(h1+h2) space
def binaryTreeLeaves2(root1, root2):
def isLeaf(node):
return not node or node.left == node.right == None
if not root1 and not root2:
return True
if (not root1) ^ (not root2):
return False
stack1 = [root1]
stack2 = [root2]
while stack1 or stack2:
if (not stack1) ^ (not stack2):
return False
tmp1 = stack1.pop()
while not isLeaf(tmp1):
if tmp1.right:
stack1.append(tmp1.right)
if tmp1.left:
stack1.append(tmp1.left)
tmp1 = stack1.pop()
tmp2 = stack2.pop()
while not isLeaf(tmp2):
if tmp2.right:
stack2.append(tmp2.right)
if tmp2.left:
stack2.append(tmp2.left)
tmp2 = stack2.pop()
if ((not tmp1) ^ (not tmp2)) or (tmp1 and tmp2 and tmp1.val != tmp2.val):
return False
return True

Resources