Oracle Interview Question
Member Technical StaffsCountry: India
Interview Type: In-Person
mark every node as a binary number,
root -> 1
left node to root -> 10
right node to root -> 11
after that -> 100-101 and 110-111
.. and so on, we will have a tree of binary numbers.
now suppose we want to know distance between '100' and '1011', follow these steps,
1. '100' would be at 'level 2' and '1011' at 'level 3'. Parent of '1011' would be '101' and it's distance '1011' would be '1'. We now have to fine distance between 100 and 101.
2. XOR '100' and '101' => '001'. Position of left most '1' in '001' gives distance of common ancestor. In this case it is '1'.
3. Distance between 100 and 1011 would be 2 * 'common ancestor distance' + ( 1011 <-> 101 distance). which is 2*1 + 1 = 3
So 3 is the distance. This way we can calculate all the distances.
Is that the approach you would use to find the neighbors of a node, i.e. for k = 1?
The number of nodes at distance k is number of neighbors of nodes at distance k-1.
And so on, recursively.
// generates a similar tree with corresponding binary positions
// binary positions are like '101' or '1011' etc
$positionsTreeRoot = formBinaryPositionTree($root);
method getNeighbours($tempRoot,$node, $k){
//getBinaryPosition returns binaryPositons from $positionsTreeRoot
$nodeBinaryPosition = getBinaryPosition($node);
$rootBinaryPosition = getBinaryPosition($tempRoot);
if( getDistance(
$nodeBinaryPosition,
$rootBinaryPosition
) == $k )
print $tempRoot->data
//continue traversal
if($tempRoot->left != NULL)
getNeighbours($tempRoot->left,$node, $k);
if($tempRoot->right != NULL)
getNeighbours($tempRoot->right,$node, $k);
}
/*
$position1 and $position2 are binary
*/
method getDistance($position1, $position2){
//binLength returns length ie, 101 > 3, 1011 > 4
$binLenDiff = binLength($position1) - binLength($position2);
if($binLenDiff < 0)
shift right $position2 abs($binLenDiff) times
else
shift right $position1 abs($binLenDiff) times
//now position1 and position2 are of equal length
$xor = $position1 ^ $position2;
return ( 2* BinLength($xor)) + abs($binLenDiff);
}
2 times 2 variations == 4 combinations exist for this problem.
2 choices
========
You can be given a key (must find the node) or given reference to the node (can access the node in question directly).
2 choices
========
Parent pointers available or not.
What does the original poster want code for?
Here is my idea for "no parent pointers"
(I would search for the Node first regardless of key vs. node ref.)"
//without parent pointers (similar if you are searching for a target key)
find_kth(Node x, Node target, k)
{
if( x == nil ) return INF; //treat it like infinity in remaining stuff
if( x == target ) {
DFS_down(x, k);
return 0; //0 hops above target node
}
//calculate number of hops away from target node
int away= MIN( find_kth(x.left, target, k), find_kth(x.right, target, k) ) + 1;
if( away<= k ) DFS_down(x, k-away); //DFS down if hops to spare
return away;
}
DFS_down(Node x, k)
{
if( x == nil ) return;
if( k == 0 ) { cout << x or x.val << " is found as desired"; return; }
DFS_down(x.right, k-1); DFS_down(x.left, k-1);
}
I tend to think of pseudocode with infinity or other sentinels (to shorten required thinking) so left it in there (my style). Fix the bugs as you desire.
Drawing a tree (not a symmetric perfect case) on paper (or your mind) makes almost all tree questions very tractable.
This should cover the two other combinations (i.e, "with parent pointers"):
//with parent pointers and given key to find (must search for Node)
find_kth(Node x, Key val, k)
{
if( x == nil ) return;
if( x.val == val ) { //at Node x, DFS down for k-th distance nodes
DFS(x, nil, k);
return 0; //current node is "0" links above target node
}
find_kth(x.right, val, k);
find_kth(x.left, val, k);
}
//called by above OR called directly in the "Parent Pointers + Node Ref." case;
DFS(Node x, Node prev, k)
{
if( x == nil ) return;
if( k == 0 ) { cout << x << " is one such Node" << endl; return; }
if( x.right != prev) DFS(x.right, x, k-1);
if( x.left != prev) DFS(x.left, x, k-1);
if( x.parent != prev) DFS(x.parent, x, k-1);
}
With a macro, we can hide some of the ugliness in the last part above
( C/C++/pseudocde style marcos)
#define safeDFS(t) if( x.t != prev ) {DFS(x.t, x, k-1);}
DFS(Node x, Node prev, k)
{
if( x == nil ) return;
if( k == 0 ) { cout << x << " is one such Node" << endl; return; }
safeDFS(right);
safeDFS(left);
safeDFS(parent);
}
Thanks to Archit Thawaria for finding a case that broke the no parent pointer code :)
In fact, we need to track 'prev' even for no-parent pointer cases (only for a small part of downward DFS)
/* collabedit.com/w57qp for further updates, anyone can do it */
//without parent pointers (similar if you are searching for a target key)
find_kth(Node x, Node target, k, *prev) <= better to have a wrapper
{
if( x == nil ) return INF; //treat it like infinity in remaining stuff
if( x == target ) {
DFS_down(x, k);
*prev=target; //set prev node as target node
return 0; //0 hops above target node
}
//calculate number of hops away from target node
int away1 = find_kth(x.left, target, k, &prev1);
int away2 = find_kth(x.right, target, k, &prev2);
if( away1 < INF ) prev = prev1, away=away1;
elif( away2 < INF ) prev = prev2, away=away2;
if( ++away <= k ) DFS_down(x, k-away, prev); //DFS down if hops to spare
*prev=x; //set prev. node as current node
return away;
}
DFS_down(Node x, Node *prev, k) //prev!=nil => dont BFS down there
{
if( x == nil ) return;
if( k == 0 ) { cout << x or x.val << " is found as desired"; return; }
if(x.right != *prev) DFS_down(x.right, nil, k-1);
if(x.left != *prev) DFS_down(x.left, nil, k-1); //remaining dont need prev
}
#include<iostream>
using namespace std;
struct Node
{
int data;
Node *left;
Node *right;
int visit;
};
Node * createNode(int data)
{
Node * n= new Node();
n->data=data;
n->left=NULL;
n->right=NULL;
n->visit=0;
return n;
}
void preorder(Node *root)
{
if(root==NULL)
return;
cout<<root->data<<" ";
preorder(root->left);
preorder(root->right);
}
void distantNodes(Node *root,int k)
{
if(root==NULL || k<0 || root->visit==1)
return;
else if(k==0 && root->visit!=1)
{
cout<<root->data<<endl;
root->visit=1;
return;
}
distantNodes(root->left,k-1);
distantNodes(root->right,k-1);
}
int distantNodesp(Node *root,int data,int k,int *flag)
{
if(root==NULL || *flag==1)
return -1;
if(root->data==data)
{
*flag=1;
distantNodes(root,k);
root->visit=1;
return k-1;
}
else
{
int l=distantNodesp(root->left,data,k,flag);
if(*flag==1)
{
distantNodes(root,l);
root->visit=1;
return l-1;
}
int r=distantNodesp(root->right,data,k,flag);
if(*flag==1)
{
distantNodes(root,r);
root->visit=1;
return r-1;
}
}
}
int main()
{
Node *root=createNode(3);
root->left=createNode(4);
root->right=createNode(5);
root->right->left=createNode(10);
root->left->left=createNode(6);
root->left->right=createNode(7);
root->left->left->left=createNode(8);
root->left->left->right=createNode(9);
root->left->right->left=createNode(11);
root->left->right->right=createNode(12);
root->left->right->right->left=createNode(15);
root->left->right->left->left=createNode(13);
root->left->right->left->right=createNode(14);
root->left->left->left->left=createNode(16);
root->left->left->left->right=createNode(17);
root->left->right->left->right->left=createNode(18);
root->left->right->left->right->right=createNode(19);
root->left->right->left->right->left->left=createNode(20);
root->left->right->left->right->left->right=createNode(21);
//preorder(root);
int flag=0;
distantNodesp(root,11,3,&flag);
return 0;
}
Correct me if my solution is wrong .
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
using namespace std;
struct node{
int data;
struct node *left,*right;
};
struct node* newnode(int data)
{
struct node* node=(struct node*)malloc(sizeof(struct node));
node->data=data;
node->left=node->right=NULL;
}
void printNodes(struct node *root,int level)
{
if(root==NULL)
return ;
if(!level)
cout<<root->data<<endl;
printNodes(root->left,level-1);
printNodes(root->right,level-1);
}
int main()
{
struct node* root=newnode(10);
root->left=newnode(20);
root->right=newnode(30);
root->left->left=newnode(40);
root->left->right=newnode(50);
root->right->left=newnode(100);
printNodes(root,2);
return 0;
}
ur code not worth reading
no comments
no work
no solve this problem at all
why you use others to read and correct your code and waste time
I am considering default implementation of Binary tree. Parent node is not given.
Using an extra class:
- Ajeet October 20, 2013