This is one of the programming questions asked during written test from Microsoft. I am giving the question and the answer that I came up with. Thing is my answer although l
It doesn't get any more elegant than this:
Node* merge2(Node* n1, Node* n2) {
n1->next = merge(n1->next, n2);
return n1;
}
Node* merge(Node* n1, Node* n2) {
return (n1 == null) ? n2 :
(n2 == null) ? n1 :
(n1->data < n2->data) ?
merge2(n1, n2) :
merge2(n2, n1);
}
Assuming that you understand recursion, this is as clear as it gets.
I should point out that this is good for an interview answer only (where presumably demonstrating clarity of thought has more impact than simply showing that you know how to write programs). In practice, you wouldn't want to merge this way, since it uses O(n)
stack depth, which likely would cause a stack overflow. Also, it's not a tail-recursion, so it's not compiler-optimizable.
So merging polygen wit AndreyT we get:
Node* merge(Node* n1, Node* n2) {
return (n1 == null) ? n2 :
(n2 == null) ? n1 :
(n1->data < n2->data) ?
(n1->next = merge(n1->next, n2), n1) :
(n2->next = merge(n2->next, n1), n2)}
I can't claim credit for this one, but it is the most concise and shows the symmetry between the two arguments, doesn't introduce any obscure helper functions. I am not sure an optimizing compiler will see a tail recursion here but I do. The indentation is a final touch.
Divide et Impera
(i.e. MergeSort)
I have created recursion function for it. Here is my solution:
Node* merge_recursion(Node* l1, Node* l2)
{
if (!l1)
return l2;
if (!l2)
return l1;
if (l1->data < l2->data) {
l1->next = merge_recursion(l1->next, l2);
return l1;
} else {
l2->next = merge_recursion(l1, l2->next);
return l2;
}
}
Store return pointer into new pointer variable (in main() / calling function) and traverse linked list on new pointer to print data, it will result sorted merged linked list.
This is my take. Unlike other solutions it identifies and skips over consecutive nodes on one list which are smaller or equal to the head node of the other list. The head of the other list is attached at the end of such sequence and the process is repeated after switching roles. This approach minimizes the number of assignments to Node.next while limiting NULL testing to single check in each iteration.
Node * merge(Node *list1, Node *list2)
{
if (!list1) return list2;
if (!list2) return list1;
Node *tmp;
// compare head nodes and swap lists to guarantee list1 has the smallest node
if (list1->val > list2->val) {
tmp = list2;
list2 = list1;
list1 = tmp;
}
Node *tail = list1;
do {
// Advance the tail pointer skipping over all the elements in the result
// which have smaller or equal value than the first node on list2
while (tail->next && (tail->next->val <= list2->val)) {
tail = tail->next;
}
// concat list2 at tail of result and make the rest after tail list2
tmp = tail->next;
tail->next = list2;
tail = list2;
list2 = tmp;
} while (list2);
return list1;
}
#include<stdio.h>
typedef struct NODE
{
int data;
struct NODE * next;
}NODE;
NODE * func(NODE*,NODE*);
int main()
{
int i;
int size;
int value;
NODE * head1,*head2,*newNode,*ptr,*final;
printf("\nPlease enter the number of elements\n");
scanf("%d",&size);
for(i=0;i<size;i++)
{
printf("List 1\n");
printf("Please enter the value number %d \n",i+1);
scanf("%d",&value);
newNode=(NODE*)malloc(sizeof(NODE));
newNode->data=value;
newNode->next=NULL;
if(i!=0)
{
ptr->next=newNode;
ptr=ptr->next;
}
if(i==0)
{
head1=newNode;
ptr=newNode;
}
}
for(i=0;i<size;i++)
{
printf("\n\nList 2\n");
printf("Please enter the value number %d \n",i+1);
scanf("%d",&value);
newNode=(NODE*)malloc(sizeof(NODE));
newNode->data=value;
newNode->next=NULL;
if(i!=0)
{
ptr->next=newNode;
ptr=ptr->next;
}
if(i==0)
{
head2=newNode;
ptr=newNode;
}
}
final=func(head1,head2);
printf("\n\n");
while (final!=NULL)
{
printf("%d -->",final->data);
final=final->next;
}
printf("NULL
");
return 0;
}
NODE* func(NODE* list1, NODE* list2)
{
NODE* mergedList,*mergeHead=NULL;
if(list1 == NULL && list2 ==NULL){//if both are NULL, return NULL
return NULL;
}
if(list1 == NULL){//if list1 is NULL, simply return list2
return list2;
}
if(list2 == NULL){//if list2 is NULL, simply return list1
return list1;
}
mergedList = (NODE*)malloc(sizeof(NODE));
if(list1->data < list2->data){//initialize mergedList pointer to list1 if list1's data is lesser
mergedList->data=list1->data;
mergedList->next=NULL;
list1 = list1->next;
}else{//initialize mergedList pointer to list2 if list2's data is lesser or equal
mergedList->data=list2->data;
mergedList->next=NULL;
list2 = list2->next;
}
mergeHead=mergedList;
while(list1!=NULL && list2!=NULL){
if(list1->data < list2->data){
mergedList->next = (NODE*)malloc(sizeof(NODE));
mergedList=mergedList->next;
mergedList->data=list1->data;
mergedList->next=NULL;
list1 = list1->next;
}else{
mergedList->next = (NODE*)malloc(sizeof(NODE));
mergedList=mergedList->next;
mergedList->data=list2->data;
mergedList->next=NULL;
list2 = list2->next;
}
}
if(list1 == NULL){//remaining nodes of list2 appended to mergedList when list1 has reached its end.
while(list2!=NULL)
{
mergedList->next = (NODE*)malloc(sizeof(NODE));
mergedList=mergedList->next;
mergedList->data=list2->data;
mergedList->next=NULL;
list2 = list2->next;
}
}else{//remaining nodes of list1 appended to mergedList when list2 has reached its end
mergedList->next = (NODE*)malloc(sizeof(NODE));
mergedList=mergedList->next;
mergedList->data=list1->data;
mergedList->next=NULL;
list1 = list1->next;
}
return mergeHead;
}