Facebook Interview Question
Software Engineer / DevelopersNice solution. :-)
The above solution uses the same amount of space your algorithm uses. At any point of time, this algorithm's queue length is same the above algorithm's two queues combined.
i think your code will go into infinite loop.
when you check the node == marker and then push marker into the queue. After the last node in the tree there is just marker left in the queue and it will keep printing newline and pushing marker infinitely.
i think you should use following condition to stop at the last marker after end of tree.
if(!queue.isEmpty()) {
queue.push(marker)
}
void printNodesByLevel(Node tree) {
Queue parentQ, childQ;
parentQ.enqueue(tree);
while(true) {
if(parentQ.isEmpty() && childQ.isEmpty()){
break;
}
if(parentQ.isEmpty() && !childQ.isEmpty()){
System.out.println("\n");
Queue tmpQ = parentQ;
parentQ = childQ;
childQ = tmpQ;
}
Node tmp = parentQ.dequeue();
System.out.println(tmp.data+" ");
NodeList children = tmp.getChildren();
for(int i = 0; i < children.length; i++) {
childQ.enqueue(children.get(i));
}
}
}
It seems it can be done with just one Queue and that is the nodeQ. node would be a child when stored in the Queue - except the root - and would be a parent when popped from the queue. Please correct meif i am missing something.
Use a dummy node - put in a null in Java for example. You'll need to add an additional check when adding children of a node to the queue - only add if a child exists, i.e. don't blindly add children of a leaf node otherwise you'll have multiple nulls in the list and the null will not act as a marker anymore
real c/c++ codes with one queue and marker
#include <cstdio>
#include <queue>
struct Node {
int data;
Node * left;
Node * right;
};
// idea:
// 1. use broadth first traverse for the queue, use a deque to store the discovered nodes.
// 2. use a pseudo node to denote the end of the level => translate to a '\n'.
void traverse(Node * root)
{
std::queue<Node *> q;
Node endl = { 0, &endl, &endl, }; // special node to mark the end of level.
q.push(root);
q.push(&endl);
while (! q.empty())
{
Node * node = q.front(); q.pop();
// check if reach the end of a level
if (node == &endl)
{
printf("\n");
//if necessary, make the end of the next level
if (! q.empty()) q.push(&endl);
continue;
}
// data processing
printf("%d ", node->data);
// push in its chidlren nodes if there's any.
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
}
int
main()
{
Node level31 = {31, 0, 0}, level32 = {32, 0, 0}, level33 = {33, 0, 0}, level34 = {34, 0, 0};
Node level35 = {35, 0, 0}, level36 = {36, 0, 0}, level37 = {37, 0, 0}, level38 = {38, 0, 0};
Node level21 = {21, &level31, &level32}, level22 = {22, &level33, &level34};
Node level23 = {23, &level35, &level36}, level24 = {24, &level37, &level38};
Node level11 = {11, &level21, &level22}, level12 = {12, &level23, &level24};
Node tree = {0, &level11, &level12};
traverse(&tree);
}
void tree_level_traversal(node *root)
{
node *temp = NULL;
if(root == NULL)
return;
/* Need a Q to do BFS */
initilizeQ();
pushQ(root);
pushQ(-1);
while(FALSE == is_Qempty())
{
temp = popQ();
if(temp == -1)
{
printf("\n");
continue;
}
printf("%4d", temp->data);
if(temp->lchild != NULL)
pushQ(temp->lchild);
if(temp->rchild != NULL)
pushQ(temp->rchild);
pushQ(-1);
}
}
No need of the marker, just count.
void level_order(Node * r)
{
std::queue<Node *> q;
q.push(r);
int current = 1;
int next = 0;
while(!q.empty()) {
Node * t = q.front();
q.pop();
std::cout << t->val;
--current;
if(t->left) {
q.push(t->left);
next++;
}
if(t->right) {
q.push(t->right);
next++;
}
if(!current) {
std::cout << std::endl;
std::swap(current, next);
}
}
}
void breadthfirstprint(node *root)
{
int prevlevel,nextlevel;
Queue q;
prevlevel=nextlevel=0;
if(root==NULL)
return;
q.enqueue(root);
prevlevel++;
while(!q.isempty())
{
node *temp = q.dequeue();
prevlevel--;
cout<<temp->value<<"\t";
if(temp->left!=NULL)
{
q.enqueue(temp->left);
nextlevel++;
}
if(temp->right!=NULL)
{
q.enqueue(temp->right);
nextlevel++;
}
if(prevlevel==0)
{
cout<<"\n";
prevlevel=nextlevel;
nextlevel=0;
}
}
return;
}
I think I have a much better solution:
vector <btree *> q; long n; btree * node;
q.push_back(bt.troot);
while(q.size())
{
n = q.size();
while(n--)
{
node = q.front();
cout << node->info <<"\t";
if(node->left)q.push_back(node->left);
if(node->right)q.push_back(node->right);
q.erase(q.begin());
}
cout << endl;
}
//C#
using System;
using System.Collections;
class Node
{
public int value;
public Node leftNode;
public Node rightNode;
public Node(int _value)
{
value = _value;
}
}
class BinarySearchTree
{
Node rootNode;
Queue[] printQueue;
public BinarySearchTree(int _value)
{
rootNode = new Node(_value);
}
public void add(int _value)
{
addRec(rootNode, _value);
printQueue = new Queue[maxDepth(rootNode)];
for (int i = 0; i < maxDepth(rootNode); i++)
{
printQueue[i] = new Queue();
}
}
public void addRec(Node _node, int _value)
{
if (_node == null) return;
if (_value < _node.value)
{
addRec(_node.leftNode, _value);
if (_node.leftNode == null)
{ _node.leftNode = new Node(_value); }
}
else if (_value >= _node.value)
{
addRec(_node.rightNode, _value);
if (_node.rightNode == null)
{
_node.rightNode = new Node(_value);
}
}
}
public void print()
{
printQueue[0].Enqueue(rootNode.value);
BreadthFirst(rootNode, 1);
for (int i = 0; i < printQueue.Length; i++)
{
while (printQueue[i].Count != 0)
{
Console.Write(printQueue[i].Dequeue());
}
Console.WriteLine();
}
}
public void BreadthFirst(Node _node, int _level)
{
if (_node == null) { return; }
if (_node.leftNode != null)
{
printQueue[_level].Enqueue(_node.leftNode.value);
}
if (_node.rightNode != null)
{
printQueue[_level].Enqueue(_node.rightNode.value);
}
++_level;
BreadthFirst(_node.leftNode, _level);
BreadthFirst(_node.rightNode, _level);
}
public int maxDepth(Node root)
{
if (root == null) { return 0; }
return 1 + Math.Max(maxDepth(root.leftNode), maxDepth(root.rightNode));
}
}
class Program
{
static void Main(string[] args)
{
BinarySearchTree myTree = new BinarySearchTree(6);
myTree.add(4);
myTree.add(5);
myTree.add(8);
myTree.add(2);
myTree.add(9);
myTree.add(11);
myTree.add(10);
myTree.print();
Console.Read();
}
}
Just do a bfs. but put a "marker" data in the queue to signal end of level.
Pseudo code
- Anonymous February 26, 2010