Microsoft Interview Question
Software Engineer / Developers Software Engineer in Testswell i posted this question
1 answer that i came across is
take 1 node at a time in 1st list. for each node traverse all nodes of 2nd list and compare.
if the two nodes converge there will be a match at some time, that is the node you need to return
it is not written in question, you can't have matching before merging point. better solution is find no of elements of both list say n1 & n2, take difference of two. traverse the bigger array first up to difference got & then traverse both list simultaneously & break wherever you are getting same address.
we could have 2 pointers.
curr1 pointing to the head node of the first list say head1 and similarly curr2 pointing to the head node of the second list.I wrote the following pseudo code,i guess this should work.
curr2=head2;
while(curr2!=NULL)
{
curr1=head1;
while(curr1!=Null)
{
if(curr1==curr2)
return curr1;
else
curr1=curr1->next;
}
curr2=curr2->next;
}
This way we ensure that each and every node in list 2 would be compared with every other node in list one the moment a match ..i.e convergence point is found the node would be returned.
compare the sizes of both; - o(n)
take difference of them, say it k - o(1)
find the bigger list - o(1)
move the bigger list k times - o(n)
now move both the smaller and larger list one at a time -o(n)
For each comparison check whther they point to the same address -o(1)
if yes return the node and exit the function -
Total time complexity - o(n)
To Anonymous on February 16, 2009
will the above solution work for these two lists?
1 2 3 4 5 6 7 8 9
1 2 5 4 6 6 7 8 9
Here we are dealing with address locations so if if the two lists point to the same address where 1 is stored then there itself you would get the point of convergence.It would not move any further.However this could be considered as atest case and surround some peice of code to endsure that if the lists are typically the same then eithere they r one and the same list or say point of covergence is first node or throw some error message.
Reverse both the lists and traverse the lists simultaneously till they diverge.
Reversing should take O(m+n) and then traversing the lists should take O(m) or O(n) depending on which is smaller.
One downside of this solution is that the lists are reversed. If the original lists have to be preserved, we might have to reverse the lists again.
Node *listMergeNode(Node *head1,Node *head2)
{
if(!head1 || !head2) return NULL;
Node *list1 = head1;
Node *list2 = head2;
while(*list1 && *list2)
{
if(*list1 == *list2)
return list1; //we have found the merge
list1 = list1->next;
list2 = list2->next;
}
return NULL; // if we reach here we have reached end of 1 of the list and no elem was found
}
If you consider the tail of the lists as a root of a tree, and the heads as leaves, this is finding the first common ancestor of the given two leaves.
Edit: If you consider the tail of the lists as a root of a tree where nodes have pointers to their parents, and the heads as leaves, this is finding the first common ancestor of the given two leaves. You should start at the leaves, calculate the depth of each (n and m) then pick the longer and traverse up abs(n - m), now we are looking at them at the same level, then traverse up level by level checking on the parent of each until they are the same or NULL.
If we are not allowed to use any extra data structure, e.g, stack or hashtable, I guess the solution would be:
assume the common node is k th node counting from the tail, then, it is n-k + 1 and m-k+1 node counting from the head. Therefore, first reverse the first link link and point the head of the first link link (now the tail) to the head of the second link link. Starting count from the head of the second link link to see how many nodes it traverse to reach itself (as there is a loop), which should be n+m-2k+1. Hence, if we count n and m at the begining, we could compute k and starting from the tail, we can identify this command node.
1. get l1=length of L1
2. get l2= length of L2
3. diff=abs(l1-l2)
4. traverse the longer list for diff times.
5. from this point both the lists will have same number of elements.
6.traverse both the lists simultaneously comparing its curr->next, return when these addresses match..
7.O(2m+2n), where m and n are lengths of lists
1. traverse list1 till end and count elements (n1) (store last node ptr)
2. traverse list2 till end and count elements (n2)
3. compare last node of two lists it should be same. else no intersection
now let the common part of two lists have k nodes then
n1= number of different nodes of list1 (pre_n1) + k
n2= number of different nodes of list2 (pre_n2) + k
n1-n2 = prev_n1 - pre_n2
by traversing the smaller list by |prev_n1-prev_n2| i.e |n1-n2| nodes we will arrive at point of intersection.
complexity
o(n1)+o(n2)+o(|n1-n2|) ~ o(n)
1) calculate the lengths of the two list, take n+m time.
- Anonymous February 17, 20092) assume n>=m, let the current elements of list1 and list2 are the heads, and then list 1 go to the (n-m)th element,
3) compare the current element , if matched, return current element, else let the current elements of two list be the next.
4) if ended, return null;