In Order traversal of a modified Binary Tree - algorithm

This was asked to me in an interview which I screwed up. We are given a binary tree , however , it is modified such that it's children are never null , if a non leaf node doesn't have a child then its right/left child points to the node itself. And for the leaf nodes , they point to the next left node and right node. For leftmost and rightmost node it will be pointing to itself and the previous/next element.
Example :
1
/ \
2 3
/ \ / \
(4 = 5 = 6 = 7)
Here 4.left = 4 , 4.right = 5 , 5.left = 4 and 5.right = 6 and so on.
We need to do an inorder traversal of this tree.
I came up with the conditions which will determine if a node is leaf node (exit condition):
if(root.right==root || root.left == root || root.left.right == root || root.right.left == root)
But couldn't combine these properly. Also we need to take care of skewed trees for which even the root satifies the condition root.left = root || root.right = right , so we will straight away get out of recursion without even traversing the whole tree.
Please help me with it. I couldn't come up with proper condition check for recursion.
We just need to do an in order traversal of this tree. Output : 4 2 5 1 6 3 7

The following algorithm should do:
visit(vertex v) {
if (v.left != v && v.left.right != v) visit(v.left)
print v
if (v.right != v && v.right.left != v) visit(v.right)
}
I think your problem was that you tried to do too many things at a time. Instead of detecting whether the vertex is a leaf or not, it would have sufficed to detect first whether it has a left child and then whether it has a right child.

If you hit a non-leaf that points to itself on the right side, but has a child on the left side, a condition like 'root.right==root' would falsely call that node a leaf. You need to use an and statement. I think this might work:
if((root.right==root && root.left.right == root) || (root.left == root && root.right.left == root) || (root.left.right == root && root.left == root))
But this will not work if you have a tree with a missing leaf in the middle. Of course if the nodes were numbered, then it would be much easier since you could just use log2 to check what level it was on compared to where it linked to.

For clarity, I put all the bizarre logic into a function (which could be inlined)
#include <stdio.h>
struct list {
struct list *prev;
struct list *next;
int val;
};
struct list arr[] =
{ {arr+1, arr+2, 1}
, {arr+3, arr+4, 2}
, {arr+5, arr+6, 3}
, {arr+3, arr+4, 4}
, {arr+3, arr+5, 5}
, {arr+4, arr+6, 6}
, {arr+5, arr+6, 7}
};
int is_leaf(struct list *p)
{
if (p->prev == p) return 1; // 4
if (p->next == p) return 1; // 7
if (p->next->prev == p) return 1; // 5,6
return 0; // non-leaves : 1,2,3
}
unsigned recurse (struct list *p)
{
int chk;
unsigned ret=1;
chk = is_leaf(p) ;
if (!chk) ret+=recurse(p->prev);
printf("%d %s\n", p->val, chk ? "leaf" : "nonLeaf" );
if (!chk) ret+=recurse(p->next);
return ret;
}
int main (void) {
unsigned cnt;
cnt = recurse (arr);
printf( "Result=%u\n", cnt );
return 0;
}
Output:
4 leaf
2 nonLeaf
5 leaf
1 nonLeaf
6 leaf
3 nonLeaf
7 leaf
Result=7

Related

Identify swapped subtrees in a binary search trees

I am looking at this challenge:
Suppose two subtrees in a binary search tree have been swapped, and that the BST property is broken. Devise an algorithm that identifies the two swapped subtrees in O(n) time.
My Thoughts
When an inorder traversal of a BST is done, the elements are sorted.
Now when two subtrees are swapped, the inorder traversal will
not be sorted. So if you compare the inorder traversal of the original
tree and the swapped one, it would be like you have taken two subsets
of a sorted array in the original one and swapped them.
But now the challenge comes to identify the corresponding subtrees, and I have no idea how to derive that from the inorder traversal.
First of all, if the tree has duplicate values and they are not always stored at the same side of their parent (that has the same value) then it is not always possible to detect a swap. Imagine a tree with the same value in many different places:
______ 8 _____
/ \
_ 8_ ___ 8 __
/ \ / \
2 8* 8* 14
/ \ / \ / \ / \
1 3 8 8 8 8 13 15
This is a valid BST. And if we were to swap the two subtrees marked with an asterisk, we would end up with a valid BST, and so there is no way to detect which subtrees were swapped. It could well have been the children of the first *-node that had been swapped, or the children of the second *-node that had been swapped. There is no way to know this.
So, it is only possible to detect a swap, if the result of the swap inserts the two involved subtrees at invalid positions. One way to ensure this, is to dictate that duplicate values should always be stored at the same side (for example at the right) of the parent node that has the same value.
Algorithm
An in-order traversal is a good idea, but the idea to then verify that the visited nodes come out in their right order is less useful.
Instead, during the traversal, keep track of the "window" (a min-max range) between which values are allowed in the currently visited subtree. As soon as you find a child that has a value outside that window, report that child node as being misplaced, and don't continue in that child's subtree (as we may assume that the subtree itself is a consistent BST).
If there was indeed a single swap, you will find two such anomalies.
Code
Here is some code (actually JavaScript), assuming you have a Node class with the usual value, left and right properties, and duplicate values can only be stored at the right of a parent node having the same value. The function takes as argument the root node of the BST:
function findSwap(root) {
let results = []; // This array (stack) will be filled with 2 nodes
// Recursive function, which will populate the array:
function recur(node, min, max) {
if (node.value < min || node.value >= max) { // Out of range!
results.push(node); // log this node, and don't bother recurring deeper
} else {
if (node.left != null) {
recur(node.left, min, node.value); // Narrow the window
}
if (node.right != null) {
recur(node.right, node.value, max); // Narrow the window
}
}
}
// Start the search with an infinite window
recur(root, -Infinity, Infinity);
return results; // Return the two nodes found as an array of nodes
}
Note that the out-of-range condition needs exactly those inequalities:
node.value < min || node.value >= max
The min value represents an allowable value, but the max does not. So the valid value range of a node is [min, max) (including min, excluding max). This follows from the extra requirement that duplicate values should always be stored at the right side. If you would decide to always store them on the left side, then the equality should be allowed on the min value and not the max value.
Implementation
Below is a runnable snippet which first creates this binary search tree:
______ 8 _____
/ \
_ 4_ __ 12 __
/ \ / \
2 6 10 14
/ \ / \ / \ / \
1 3 5 7 9 11 13 15
It then swaps the subtree at 6 with the subtree at 10. And finally it calls the above function and reports the result:
function findSwap(root) {
let results = [];
function recur(node, min, max) {
if (node.value < min || node.value >= max) {
results.push(node);
} else {
if (node.left) {
recur(node.left, min, node.value);
}
if (node.right) {
recur(node.right, node.value, max);
}
}
}
recur(root, -Infinity, Infinity);
return results;
}
// Define the Node class
class Node {
constructor(value) {
this.value = value;
this.left = this.right = null;
}
add(...values) { // Allow adding more than one value with one call
for (let value of values) {
if (value < this.value) {
if (this.left) this.left.add(value);
else this.left = new Node(value);
} else {
if (this.right) this.right.add(value);
else this.right = new Node(value);
}
}
}
}
// Demo:
// Create a complete binary tree with values 1 through 15
let root = new Node(8); // root
root.add( 4, 12, // level 1
2, 6, 10, 14, // level 2
1, 3, 5, 7, 9, 11, 13, 15); // level 3
// Perform a swap of the subtree rooted in 6 and in 10:
[root.left.right, root.right.left] = [root.right.left, root.left.right];
// Call the function:
let result = findSwap(root);
// Report which subtrees were swapped
console.log(result[0].value, result[1].value); // 10, 6
Of course, if the tree did not have a swap of exactly two distinct subtrees, then the returned array will not always give reliable information, since it assumes that a wrongly attached subtree is itself still consistent.
But if the returned array is empty, you may conclude that the BST is fine.
Detecting move of one subtree
In comments you gave an example of a subtree that was moved (not swapped with another):
In that case the above code will return just the misplaced subtree, but it will not give information about where this subtree came from.
If also this case should be covered, then we need to change the output, because it doesn't really help to list the other (degenerate) "subtree" as null. So then I propose to have the output state which is the parent and the side of the edge where the subtree was cut away.
The above algorithm could be adapted so that it will do some post processing in case there is only one anomaly found: in that case a simple binary search will find the insertion spot for that misplaced subtree. This post processing represents O(logn) time complexity, so it does not impact the overall linear time complexity.
Here is the adapted code, together with the example you had posted:
function findSwap(root) {
let results = [];
function recur(node, parent, side, min, max) {
if (node.value < min || node.value >= max) {
results.push({parent, side, node});
return;
}
if (node.left != null) {
recur(node.left, node, "left", min, node.value);
}
if (node.right != null) {
recur(node.right, node, "right", node.value, max);
}
}
recur(root, null, "root", -Infinity, Infinity);
// Post processing:
if (results.length === 1) {
// It was not a swap, but a move
let value = results[0].node.value;
// Look up the insertion point for the misplaced value (and its subtree)
let parent = root;
while (results.length < 2) {
if (value < parent.value) {
if (parent.left == null) {
result.push({parent, side: "left", node: null });
} else {
parent = parent.left;
}
} else {
if (parent.right == null) {
results.push({parent, side: "right", node: null });
} else {
parent = parent.right;
}
}
}
}
return results;
}
// Define the Node class
class Node {
constructor(value) {
this.value = value;
this.left = this.right = null;
}
add(...values) { // Allow adding more than one value with one call
for (let value of values) {
if (value < this.value) {
if (this.left) this.left.add(value);
else this.left = new Node(value);
} else {
if (this.right) this.right.add(value);
else this.right = new Node(value);
}
}
}
}
// Demo (as in image):
let root = new Node(5); // root
root.add( 3, 8, // level 1
2, 4, 7, 9); // level 2
// Perform the move of the subtree rooted in 8, below the node 4
root.left.right.right = root.right;
root.right = null;
// Call the function:
let result = findSwap(root);
// Report which subtrees were swapped
function edgeName(edge) {
return "the " + edge.side + " child (" + (edge.node?.value??null) + ") of node " + edge.parent.value;
}
console.log(edgeName(result[0]) + " was swapped with " + edgeName(result[1]));

Convert one BST to become structurally identical to other in minimum number of insertions

Given two binary trees T1 and T2, you have to find minimum number of insertions to be done in T1 to make it structurally identical to T2. Return -1 if not possible.
Notes
Assume insertions are done in a normal fashion in the BSTs.
Assume while inserting, if the value of a node v is equal to value being inserted, we insert it in left subtree of node v.
You can insert any positive or negative integer.
Serialization : for each index i, 2*i is left child and 2*i+1 is right child, -1 if no child
Input 1:
T1: 10 9 20
T2: 5 2 7 1 -1 -1 -1
10 5
/\ / \
9 20 2 7
/
1
If you insert 8 into T1, it will be structurally identical to T2. Hence answer is 1.
Input 2:
T1: 10 9 20
T2: 5 -1 7
10 5
/\ \
9 20 7
You cannot make T1 and T2 structurally identical. Hence answer is -1.
My this code got accepted on platform, but i doubt it's correctness.
I am not sure weather by allowing insertion of equal elements this code is correct or not.
Do we still need to check for value ranges to insert nodes in the tree ?
int Solution::cntMatrix(TreeNode* A, TreeNode* B) {
if(A==NULL && B==NULL) return 0;
if(A==NULL) {
int L=cntMatrix(A,B->left); if(L==-1) return -1;
int R=cntMatrix(A,B->right);if(R==-1) return -1;
return L+R+1;
}
if(B==NULL) return -1;
int L=cntMatrix(A->left,B->left); if(L==-1) return -1;
int R=cntMatrix(A->right,B->right); if(R==-1) return -1;
return L+R;
}
Source : InterviewBit
You can solve this using Breadth first search.
compare the no of nodes at each level if T1 has more nodes at a level than T2 simply return -1
else use a variable say count and at each level you can simply docount+=(No of nodes of T2 at level N) - (No of nodes of T1 at level N)
and then return count thats it.
If T1 has m elements and T2 has n elements, then the number of insertions required is n-m. Obviously. Because if you insert more, then T1 will have more elements and can never be structurally equivalent to T2.
The other questions are more interesting.
Is it even possible? Simultaneously traversing both trees should answer this question.
Most interesting question is, what to insert? For this you need to maintain a (min, max) limits and update it accordingly. Whenever you need to insert a number, pick from this range.
I am leaving out details for you to work out. But this is the gist.
Following solution is more accurate in terms of accuracy and performance:
public int cntMatrix(TreeNode A, TreeNode B) {
return cntMatrixUtil(A,B,Integer.MIN_VALUE,Integer.MAX_VALUE);
}
public int cntMatrixUtil(TreeNode A, TreeNode B, int min,int max) {
if(A!=null && B==null)
return -1;
int inserts=-1;
if(A!=null && B!=null)inserts = 0;
else inserts = 1;
if(B==null && A==null)return 0;
if(B !=null && A ==null)A = new TreeNode(min+(max-min)/2);
int left = cntMatrixUtil(A.left, B.left, min, A.val);
int right = cntMatrixUtil(A.right, B.right, A.val, max);
if(left==-1 || right ==-1)return -1;
return inserts + left + right;
}
you can try something like this, in python :
(also DFS would be faster for this problem since you could return -1 faster)
count = 0
queue = [(T1,T2)]
while queue:
(t1, t2) = queue.pop()
if not t1 and not t2: continue
if t1 and not t2: return -1
if t1 and not t2: count +=1
queue.append((t1.left if t1 else None, t2.left))
queue.append((t1.right if t1 else None, t2.right))
return count
Consider the following case:
5 10 8 -1 -1 -1
13 5 0 -1 -1 1 -1 3 2 -1 -1 3 -1 -1
This should ideally return -1, since tree 1 cannot be structurally converted to tree 2. However your computed value would be 4.
int cntMatrixUtil(TreeNode* A, TreeNode*B, int l1, int h1){
if(A == NULL && B == NULL) return 0;
if(A!= NULL && B == NULL) return -1;
if(A == NULL && B != NULL){
//you have to keep checking for all possible values at this position
for(int i=l1; i<=h1; i++){
int cntLeft = cntMatrixUtil(NULL, B->left, l1, i);
int cntRight = cntMatrixUtil(NULL, B->right, i+1, h1);
if(cntLeft == -1 || cntRight == -1) continue;
return cntLeft+cntRight+1;
}
return -1;
}else{
int cntLeft = cntMatrixUtil(A->left, B->left, l1, A->val);
int cntRight = cntMatrixUtil(A->right, B->right, A->val+1, h1);
if(cntLeft == -1 || cntRight == -1) return -1;
return cntLeft + cntRight;
}
}
int Solution::cntMatrix(TreeNode* A, TreeNode* B) {
return cntMatrixUtil(A,B, INT_MIN, INT_MAX);
}

Check if a binary tree is subtree of another binary tree

To check if a binary tree is subtree of another tree ,I was thinking that lets store the inorder and preorder traversal of the tree as strings(like assigning characters to each node) and then do a substring match to check if the tree is subtree or not. Will this approach work ?
Not sure who picked #genisage's answer as correct. Inorder with preorder/postorder substring approach is the best solution for this problem. In the example #genisage mentioned pre-order traversals are 1 2 and 2 2 1. 1 2 is not a substring of 2 2 1 and the answer is false.
no, it won't. consider a possible subtree consisting of a root node containing 1, and a left child containing 2. And a second tree with root 1, left child 2, and right child 1.
It's clear that the first is not a subtree of the second but your method would say that it is since the preorder traversals are 1 2 and 1 2 1, and the inorder traversals are 2 1 and 2 1 1.
You would need to add null values when they’re encountered to differentiate, making the preorder traversal 1 2 null and 1 2 1 and the inorder 2 1 null and 2 1 1 which is not a sub tree.
Given two binary trees, check if the first tree is subtree of the second one. A subtree of a tree T is a tree S consisting of a node in T and all of its descendants in T. The subtree corresponding to the root node is the entire tree; the subtree corresponding to any other node is called a proper subtree.
For example, in the following case, tree S is a subtree of tree T.
Tree S
10
/ \
4 6
\
30
Tree T
26
/ \
10 3
/ \ \
4 6 3
\
30
Traverse the tree T in preorder fashion. For every visited node in the traversal, see if the subtree rooted with this node is identical to S.
#include <stdio.h>
#include <stdlib.h>
/* A binary tree node has data, left child and right child */
struct node
{
int data;
struct node* left;
struct node* right;
};
/* A utility function to check whether trees with roots as root1 and root2 are identical or not */
bool areIdentical(struct node * root1, struct node *root2)
{
/* base cases */
if(root1 == NULL && root2 == NULL)
return true;
if(root1 == NULL || root2 == NULL)
return false;
/* Check if the data of both roots is same and data of left and right subtrees are also same */
return (root1->data == root2->data &&
areIdentical(root1->left, root2->left) &&
areIdentical(root1->right, root2->right) );
}
/* This function returns true if S is a subtree of T, otherwise false */
bool isSubtree(struct node *T, struct node *S)
{
/* base cases */
if (S == NULL)
return true;
if (T == NULL)
return false;
/* Check the tree with root as current node */
if (areIdentical(T, S))
return true;
/* If the tree with root as current node doesn't match then
try left and right subtrees one by one */
return isSubtree(T->left, S) ||
isSubtree(T->right, S);
}
/* Helper function that allocates a new node with the given data
and NULL left and right pointers. */
struct node* newNode(int data)
{
struct node* node = (struct node*)malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return(node);
}
/* Driver program to test above function */
int main()
{
/* Construct the following tree
26
/ \
10 3
/ \ \
4 6 3
\
30
*/
struct node *T = newNode(26);
T->right = newNode(3);
T->right->right = newNode(3);
T->left = newNode(10);
T->left->left = newNode(4);
T->left->left->right = newNode(30);
T->left->right = newNode(6);
/* Construct the following tree
10
/ \
4 6
\
30
*/
struct node *S = newNode(10);
S->right = newNode(6);
S->left = newNode(4);
S->left->right = newNode(30);
if( isSubtree(T, S) )
printf("Tree S is subtree of tree T");
else
printf("Tree S is not a subtree of tree T");
getchar();
return 0;
}
Output: Tree S is subtree of tree T

Find the least common parent in a binary tree?

This question might have been asked by a lot of guys but, it is kinda different. We have a binary tree. And you are given two nodes p & q. We have to find the least common parent. But you dont have root node pointer which points to the root. You are provided with two inbuilt functions which are:
1) BOOL same(node *p, node *q); -> returns true if the nodes are same or else false.
2) node* parentNode(node *c); -> returns a node which is the parent of the current node.
If the node c is actually root then parentNode function will return you with aNULL value.
Using the functions we have to find the least common parent of the tree.
Step1: Using parentNode function find the distance d1 of the node p from root. similarly find distance d2 of node q from the root. (say, d2 comes out ot be greater than d1)
Step 2: Move the farther node(whose ever d-value was greater) pointer d2-d1 steps towards root.
Step3: Simultaneously move pointers p and q towards root till they point to same node and return that node.
Basically it will be like finding the merge point of two linked-lists. Check the below link:
Check if two linked lists merge. If so, where?
Time complexity: O(N)
Your code would look somewhat along the lines:
node* LCP(node* p, node *q){
int d1=0, d2=0;
for(node* t= p; t; t = parentNode(p), ++d1);
for(node* t= q; t; t = parentNode(q), ++d2);
if(d1>d2){
swap(d1, d2);
swap(p, q);
}
for(int i=0; i<(d2-d1); ++i)
q = parentNode(q);
if( same(p, q)){
return parentNode(p);
}
while( !same(p, q)){
p = parentNode(p);
q = parentNode(q);
}
return p;
}
Assuming C++:
node* leastCommonParent(node *p, node *q)
{
node *pParent = parentNode(p);
while(pParent != 0)
{
node *qParent = parentNode(q);
while(qParent != 0)
{
if (0 == same(pParent, qParent))
return pParent;
qParent = parentNode(qParent);
}
pParent = parentNode(pParent);
}
return 0;
}
UPDATE: A version without explicitly declared variables using recursion follows. I'm sure it can be improved and would probably never use it in production code in the current form.
node* qParent(node *p, node *q)
{
if (p == 0 || q == 0)
return 0;
if (same(p, q) == 0)
return p;
return qParent(p, q->parent);
}
node* pParent(node *p, node *q)
{
return qParent(p, q) ? qParent(p, q) : pParent(p->parent, q);
}
node * result = pParent(p, q);

How to count the number of right children in a binary tree?

How to count the number of right children in a binary tree?
This means that I only want the children marked as right.
Ex.
(Left | Right)
F(Root)
G | H
T U | I J
The right children would be U,H,and J.
What would be the algorithm to find these.
int count(Tree *r){
if(r == NULL) return 0;
int num_l=0, num_r=0;
if(r->left != NULL)
num_l = count(r->left);
if(r->right != NULL)
num_r = count(r->right)+1;
return num_l+num_r
}
In recursive approach,
You would be calling a function to traverse your tree,
for current node, you need to:
check if current node has right child (then increment the counter), and then call the function recursively for right node.
check if current node has left child, call the function recursively for left node.
This should work.
Do a simple traversal on the tree (i.e. post order, in order) and for each node do +1 if it has right child.
Example (didn't try to compile and check it):
int countRightChildren(Node root)
{
if (root == null) return 0;
int selfCount = (root.getRightChild() != null) ? 1 : 0;
return selfCount + countRightChildren(root.getLeftChild()) + countRightChildren(root.getRightChild());
}
You can do it recursively as:
If tree does not exist, there are no
R children.
If tree exists, then # R children = #
R children in R-subtree + # R
children in L-subtree
.
int countRChildren(Node *root) {
if(!root) // tree does not exist.
return 0;
// tree exists...now see if R node exits or not.
if(root->right) // right node exist
// return 1 + # of R children in L/R subtree.
return 1 + countRChildren(root->right) + countRChildren(root->left);
else // right nodes does not exist.
// total count of R children will come from left subtree.
return countRChildren(root->left);
}
This is include how i build the struct
struct Item
{
int info;
struct Item* right;
struct Item* left;
};
typedef struct Item* Node;
int countRightSons(Node tree)
{
if(!tree)
return 0;
if(tree->right != NULL)
return 1 + countRightSons(tree->right) + countRightSons(tree->left);
return countRightSons(tree->left);
}
Simple recursive approach,
check (even if not needed) for all the 4 possibilities:
left and right does not exists
left and right exists
left exists and right doesnt
right exists and left doesnt
public static int countRightChildren(BST tree) {
if (tree.root==null) return Integer.MIN_VALUE;
return countRightChildren(tree.root);}
public static int countRightChildren(Node curr) {
if (curr.right==null&&curr.left==null) return 0;
else if (curr.right!=null&&curr.left==null)
return curr.right.data+countRightChildren(curr.right);
else if (curr.right==null&&curr.left!=null)
return countRightChildren(curr.left);
else if (curr.right!=null&&curr.left!=null)
return curr.right.data+countRightChildren(curr.left)+countRightChildren(curr.right);
return Integer.MIN_VALUE;
}

Resources