I have been asked in an interviews to print the boundary of the Binary Tree. For example.
1
/ \
2 3
/ \ / \
4 5 6 7
/ \ \
8 9 10
Answer will be : 1, 2, 4, 8, 9, 10, 7, 3
I have given the following answer.
First Method :
I have used a Bool variable to solve the above problem.
void printLeftEdges(BinaryTree *p, bool print) {
if (!p) return;
if (print || (!p->left && !p->right))
cout << p->data << " ";
printLeftEdges(p->left, print);
printLeftEdges(p->right, false);
}
void printRightEdges(BinaryTree *p, bool print) {
if (!p) return;
printRightEdges(p->left, false);
printRightEdges(p->right, print);
if (print || (!p->left && !p->right))
cout << p->data << " ";
}
void printOuterEdges(BinaryTree *root) {
if (!root) return;
cout << root->data << " ";
printLeftEdges(root->left, true);
printRightEdges(root->right, true);
}
His Response : You have used Bool variable so many times. Can you solve this without using that.
Second Method :
I simply used tree traversal to solve this problem.
1. Print the left boundary in top-down manner.
2. Print all leaf nodes from left to right, which can again be sub-divided into two sub-parts:
2.1 Print all leaf nodes of left sub-tree from left to right.
2.2 Print all leaf nodes of right subtree from left to right.
3. Print the right boundary in bottom-up manner.
His Response : He was not happy with this method too. He told that you are traversing the tree 3 times. That is too much. Give another solution if you have any.
Third Method :
This time i have went for Level Order traversal (BFS).
1: Print starting and ending node of each level
2: For each other node check if its both the children are <b>NULL</b> then print that node too.
His Response : He was not seems happy with this method too because this method takes extra memory of order O(n).
My question is that Tell me a method which traverse tree single times, do not use any Bool variable and do not use any extra memory. Is it possible?
I guess this should do the trick:
traverse(BinaryTree *root)
{
if (!root) return;
cout << p->data << " ";
if (root->left ) traverseL(root->left ); //special function for outer left
if (root->right) traverseR(root->right); //special function for outer right
}
traverseL(BinaryTree *p)
{
cout << p->data << " ";
if (root->left ) traverseL(root->left ); //still in outer left
if (root->right) traverseC(root->right);
}
traverseR(BinaryTree *p)
{
if (root->left ) traverseC(root->left );
if (root->right) traverseR(root->right); //still in outer right
cout << p->data << " ";
}
traverseC(BinaryTree *p)
{
if (!root->left && !root->right) //bottom reached
cout << p->data << " ";
else
{
if (root->left ) traverseC(root->left );
if (root->right) traverseC(root->right);
}
}
Start with the traverse
function.
Got rid of the null-queries at the beginning of each method (avoids one function call at each end).
Does not need bool variables, simply uses three different traversal methods:
- one for the left edge, outputting the node before traversal
- one for the right edge, outputting the node after traversal
- one for all other nodes, outputting the node if there are no siblings.
Below is a recursive solution in Python3 with time complexity O(n). Algorithm here is to print left most nodes from top to bottom, leaf nodes from left to right and right most nodes from bottom to top. Adding boolean flags (isLeft,isRight)
for left and right tree traversal simplifies the code and drives the time complexity of O(n).
#Print tree boundary nodes
def TreeBoundry(node,isLeft,isRight):
#Left most node and leaf nodes
if(isLeft or isLeaf(node)): print(node.data,end=' ')
#Process next left node
if(node.getLeft() is not None): TreeBoundry(node.getLeft(), True,False)
#Process next right node
if(node.getRight() is not None):TreeBoundry(node.getRight(), False,True)
#Right most node
if(isRight and not isLeft and not isLeaf(node)):print(node.data,end=' ')
#Check is a node is leaf
def isLeaf(node):
if (node.getLeft() is None and node.getRight() is None):
return True
else:
return False
#Get started
#https://github.com/harishvc/challenges/blob/master/binary-tree-edge-nodes.py
TreeBoundry(root,True,True)
Method O(n) No extra space and single traversal of tree.
I divided the Tree Nodes into four types of nodes
Type 1 -> Nodes which form the left boundary(eg 8)
Type 0 -> Nodes which do not form the boundar(eg 12)
Type 3 -> Nodes which form the right boundary(eg 22)
Leaf Nodes(eg 4,10,14)
In my method i am just doing recurrsion method of tree traversal (just modified) where my function is of this form
void recFunc(btNode *temp,int type)
{
//Leaf Nodes
if((temp->left == NULL)&&(temp->right == NULL))
cout << temp->data << " ";
// type -1 Nodes must be printed before their children
else if(type == 1)cout << temp->data << " ";
else {;}
if(type == 3)
{
if(temp->left)recFunc(temp->left,0);
if(temp->right)recFunc(temp->right,3);
//type 3 nodes must be printed after their children
cout << temp->data << " ";
}
else if(type == 1)
{
if(temp->left)recFunc(temp->left,1);
if(temp->right)recFunc(temp->right,0);
}
else if(type == 0)
{
if(temp->left)recFunc(temp->left,0);
if(temp->right)recFunc(temp->right,0);
}
else {;}
}
where i have modofied the
- In my recurrsive function Nodes of type 1 must make their left nodes
as type 1 and must be printed before calling their children(if they
exist)
- Nodes Of Type 3 must be printed in reverse order .So they must be
printed after call to their children.They must also assign their
right children as Type 3 Nodes
- Nodes Of Type 0 must not be printed and they assign their children as
type 0 Nodes
- Leaf Nodes must be directly printed only and return
Link to Code