National Instruments Interview Question
Software Engineer in Testsuse recursion.
pad zeroes to either of the linked list so tat they are equal. here is the algo after that.
sum(n1, n2, &10, &false);
Sum(n1, n2, &temp, &carry)
{
if(!n1 || !n2)
return;
if(carry)
{
if(n1 == 0)
cout<< (n1->data + (--temp)) - n2->data;
else
{
n1->data --;
carry = false;
temp = 10;
}
}
if(n1->data < n1->data)
{
cout<< (n1->data + temp) - n2->data;
carry = true;
temp--;
}
else
cout<< (n1->data) - (n2->data);
sum(n1->next, n2->next, temp, carry);
}
ideone[dot]com/Nq3hI
O(n) time and space. I did not choose to use recursion because the question says "very long lists" - which would mean too much of space and func call overhead.
First of all you are storing the numbers in arrays.
For large numbers, this is definitely not allowed.
Further, every one knows subtraction.
The following piece of code :
c[i]=(a[i]+10)-b[i];
a[i-1]=a[i-1]-1;
is the challenging part since in linked list it is difficult to achieve.
So I think this solution is unacceptable.
if allowed to change link list B then
add zeroes at the start of B till both link list length is equal
then start subtracting from head till end.
at any point if A.data>=B.data then the resultant link list will have a node of value
A.data-Ba.data
else if B.data is greater, resultant will have a node of value 10+A.data-B.data. and the value of previous node in the resultant link list will be decremented by 1. ( will need to maintain a previous pointer)
after traversing the whole link list, resultant link list will have the answer.
restore link list B
since we are subtracting only 1 number from A , the borrow required will not propoagate more than 1 digit to right. hence we can subtract from head as well.
eg
A 5 4 2 0 0 9 0 0
B 1 9 9
pad zeroes to B
A 5 4 2 0 0 9 0 0
B 0 0 0 0 0 1 9 9
C is resultant link list
start from head
5>0 C 5
4>0 C 5 4
2>0 C 5 4 2
0>=0 C 5 4 2 0
0>=0 C 5 4 2 0 0
9>1 C 5 4 2 0 0 8
0<9 hence v=next value will be 10 + 0 -9 =1 and prev node is decremented. hence 8 becomes 7 C is 5 4 2 0 0 7 1
0<9 similar to above value is 10 +0 -9 =1 and previous 1 becomes 0
C is 5 4 2 0 0 7 0 1
this is assuming A>B if not which we can come to know while examining the head values
call same function with the lists swapped and will need to append - sign at head.
edit
"since we are subtracting only 1 number from A , the borrow required will not propoagate more than 1 digit to right."
typo. i meant left and not right.
Why cannt we convert it in to decimal subtract it and then convert back to linked list
converting will take only o(n) and the subtracting o(1) and again converting o(n).
that won't work for a very long linked list, e.g. a long type variable cannot hold 9999999999999999999999999999
find the length of another LL (to be Subtracted)say 3 in this case
take a ponter p1 pointing to 1st element of list A and another pointer p2 pointing to 3rd element of list A.when p2 will reach end p1 will at third last number and now we can easily subtract list B from it...
Since, the linked lists can be very large, we obviously cannot convert them into a number and subtract using a unary minus. So the trick to solve this question is to traverse the list and subtract the value of list1 with the value of list2 and also subtract the borrow. If the result is negative, add 10 to the final result.
I was thinking something along the lines of.
Start identifying the both ll's length at the same time.
If you see one of them ending
stop
////now you know the length of the smaller one. Let = X
Now identify the X digits from the end for the bigger ll. (Using one pointer and another pointer legging behind by X traversing once. It's O(n))
Do math.
From what I see here complexity is minimized, actually its O(n) and no extra space.
I was thinking something along the lines of.
Start identifying the both ll's length at the same time.
If you see one of them ending
stop
////now you know the length of the smaller one. Let = X
Now identify the X digits from the end for the bigger ll. (Using one pointer and another pointer legging behind by X traversing once. It's O(n))
Do math.
From what I see here complexity is minimized, actually its O(n) and no extra space.
//find the length of both list l1, l2
//append l1-l2 nodes in the second list in front
fun(list a, list b){
if(a==null)
return 0;
int borrow=fun(a.next,b.next,c)
Node newNode=new Node();
if(a.data>b.data){
newNode.data=a.data-b.data-borrow;
newNode.next=c;//front insertion
c=newNode;
return 0;
}
else if(a.data==b.data){
if(borrow==0){
newNode.data=0;
newNode.next=c;
c=newNode;
return 0;
}
else{
newNode.data=9;
newNode.next=c;
c=newNode;
return 1;
}
else{
newNode.data=a.data+10-b.data-borrow
newNode.next=c;
c=newNode;
return 1;
}
}
}
hey, we can form complete decimal number by traversing from head to last node and then taking difference between the two and again breaking them in single digits & storing them in third linked list.....
- vick August 16, 2010