Array folding into a single element - c++

This is an interview question not a homework.
Given a array of 1 to 2 ^N. For eg: 1 2 3 4 5 6 7 8 (2^3) .Imagine this array is written on a paper, we need to fold this into half, so that the left half will be mirrored and then moved underneath the right half like this
1 2 3 4 5 6 7 8
left | right
half | half
becomes
5 6 7 8
4 3 2 1
And the next fold we take the right half instead, mirroring it and moving it below the left half,
5 6
4 3
8 7
1 2
The paper has to be folded, changing direction (left-vs-right) each time, until we have all the elements in the single column like this
6
3
7
2
5
4
8
1
My solution,
First step :
Create a linked list for the second half of the original array, and reverse the first half and connect it with head pointers,
5 6 7 8
| | | |
4 3 2 1
And store the head pointers of linked list in an array called headarray
Iteratively :
fold the head array, for each fold either the first half and second half headers will be linked. Delete the head pointers from the headarray once it is linked.
Continue until w have a single head pointer in the head array.
But the interviewer asked me to solve it in stack. Could anyone help in getting this solved in stack and also point out if have done any mistake in my solution. Thanks in advance.

This problem can be solved by using a stack and the original array. I will not code the solution for you, but I will point out how to solve it.
push the array elements on to the stack following the rules we'll discuss further down
right after that pop the stack back into the array starting at index 0
repeat until the end condition is fulfilled
Rule for filling the stack:
initially consider your array as one 'segment'
divide the segment in half; the first half you will iterate in reverse order(right->left), the second one in natural order (left->right)
You start pushing on to the stack from the end of the array:
if the iteration is Odd, push the odd half(s) first,
if the iteration is even start with the even half(s) first
repeat, and keep half-ing your segments until they contain only one element; this is your stop condition
This is a little abstract, so let's consider your example:
iter=1 ->1234 <-5678 Arrows show the direction of iteration
start from the end and fill the stack; inter is odd so start with the first odd half encountered
5
6
7
8
4 <-notice that the order of pushing the halfs on the stack is shown by the arrows
3
2
1
pop the stack back : 5 6 7 8 4 3 2 1
Continue dividing the halfs:
iter=2 <-56 ->78 <-43 ->21; odd halfs 56,43; even halfs 78,21
start from the end and fill the stack; inter is even so start with the first even halfs
5
6
4
3
8 <-even halfs end, odd halfs start
7
1
2
Pop the stack back: 5 6 4 3 8 7 1 2
Divide the segments again, since there will be only one element in each new half the arrows are used just to highlight the rule:
iter=3 ->5 <-6 ->4 <-3 ->8 <-7 ->1 <-2
iter is odd, so fill the stack odd halfs first
6
3
7
2
5
4
8
1
Pop the stack back, and you are done: 63725481
I hope this makes sense; happy coding :)

I have found a law, the element in array whose index is (2*n-1, 2*n), the n is odd, always array before the rest elements whatever direction your folded. For example, the array 12345678, the elements 2367 always are front of the 1458. Now I have used dichotomy for getting two arrays. Next you maybe find the law in two arrays. I hope this can help you.

Maybe your interviewer expected something like:
private int[] Fold(int pow)
{
if (pow < 0)
throw new Exception("illegal input");
int n = 1;
for (int factor = 1; factor <= pow; factor++)
n *= 2;
Stack<int> storage = new Stack<int>(n);
this.Add(n, 1, storage);
int[] result = new int[n];
for (int k = 0; k < n; k++)
result[k] = storage.Pop();
return result;
}
private void Add(int n, int value, Stack<int> storage)
{
storage.Push(value);
int m = n;
while (true)
{
int mirror = m + 1 - value;
if (mirror <= value)
break;
this.Add(n, mirror, storage);
m /= 2;
}
}
{ demonstrating that you know about stacks AND about recursion ;-) }

Here's a recursive solution turned iterative; hence a stack, although probably not as intended. The function returns the starting position of an element based on the given position. It seems to be of time O(1/2n(log n + 1)) and space O(log n).
JavaScript Code:
function f(n,y,x,l){
var stack = [[n,y,x,l]];
while (stack[0]){
var temp = stack.pop();
var n = temp[0], y = temp[1], x = temp[2], l = temp[3];
var m = 1 << l;
if (m == 1)
return x;
if (l % 2 == 0){
if (y > m / 2)
stack.push([n * 2,y - m / 2,n + n - x + 1,l - 1]);
else
stack.push([n * 2,y,x,l - 1]);
} else if (y > m / 2){
stack.push([n * 2,y - m / 2,n - x + 1,l - 1]);
} else
stack.push([n * 2,y,x + n,l - 1]);
}
}
function g(p){
var n = 1 << p;
for (var i=1; i<n; i+=2){
var a = f(1,i,1,p);
console.log(a);
console.log(n - a + 1);
}
}
g(3)

Related

To make array identical by swapping elements

There are 2 i/p array's. They are identical when they have exactly same numbers in it. To make them identical, we can swap their elements. Swapping will have cost. If we are swapping a and b elements then cost = min(a, b).
While making array's identical, cost should be minimum.
If it is not possible to make array identical then print -1.
i/p:
3 6 6 2
2 7 7 3
o/p :
4
Here I have swapped (2,7) and (2,6). So min Cost = 2 + 2 = 4.
Logic :
Make 2 maps which will store frequency of i/p array's elements.
if element "a" in aMap is also present in bMap, then we have to consider number of swapping for a = abs(freq(a) in aMap - freq(a) in bMap)
if frequency of elements is "odd", then not possible to make them identical.
else , add total swaps from both maps and find cost using
cost = smallest element * total swaps
Here is the code
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
int main()
{
int t;
cin >> t;
while(t--)
{
int size;
long long int cost = 0;
cin >> size;
bool flag = false;
map<long long int, int> aMap;
map<long long int, int> bMap;
// storing frequency of elements of 1st input array in map
for( int i = 0 ; i < size; i++)
{
long long int no;
cin >> no;
aMap[no]++;
}
// storing frequency of elements of 2nd input array in map
for(int i = 0 ; i < size; i++)
{
long long int no;
cin >> no;
bMap[no]++;
}
// fetching smallest element (i.e. 1st element) from both map
long long int firstNo = aMap.begin()->first;
long long int secondNo = bMap.begin()->first;
long long int smallestNo;
// finding smallest element from both maps
if(firstNo < secondNo)
smallestNo = firstNo;
else
smallestNo = secondNo;
map<long long int, int> :: iterator itr;
// trying to find out total number of swaps we have to perform
int totalSwapsFromA = 0;
int totalSwapsFromB = 0;
// trversing a map
for(itr = aMap.begin(); itr != aMap.end(); itr++)
{
// if element "a" in aMap is also present in bMap, then we have to consider
// number of swapping = abs(freq(a) in aMap - freq(a) in bMap)
auto newItr = bMap.find(itr->first);
if(newItr != bMap.end())
{
if(itr->second >= newItr->second)
{
itr->second -= newItr->second;
newItr->second = 0;
}
else
{
newItr->second -= itr->second;
itr->second = 0;
}
}
// if freq is "odd" then, this input is invalid as it can not be swapped
if(itr->second & 1 )
{
flag = true;
break;
}
else
{
// if freq is even, then we need to swap only for freq(a)/ 2 times
itr->second /= 2;
// if swapping element is smallest element then we required 1 less swap
if(itr->first == smallestNo && itr->second != 0)
totalSwapsFromA += itr->second -1;
else
totalSwapsFromA += itr->second;
}
}
// traversing bMap to check whether there any number is present which is
// not in aMap.
if(!flag)
{
for(itr = bMap.begin(); itr != bMap.end(); itr++)
{
auto newItr = aMap.find(itr->first);
if( newItr == aMap.end())
{
// if frew is odd , then i/p is invalid
if(itr->second & 1)
{
flag = true;
break;
}
else
{
itr->second /= 2;
// if swapping element is smallest element then we required 1 less swap
if(itr->first == smallestNo && itr->second != 0)
totalSwapsFromB += itr->second -1;
else
totalSwapsFromB += itr->second;
}
}
}
}
if( !flag )
{
cost = smallestNo * (totalSwapsFromB + totalSwapsFromA);
cout<<"cost "<<cost <<endl;
}
else
cout<<"-1"<<endl;
}
return 0;
}
No error in the above code but giving wrong answer and not getting accepted.
Can anyone improve this code / logic ?
Suppose you have 2 arrays:
A: 1 5 5
B: 1 4 4
We know that we want to move a 5 down and a 4 up, so we have to options: swapping 4 by 5 (with cost min(4, 5) = 4) or using the minimum element to do achive the same result, making 2 swaps:
A: 1 5 5 swap 1 by 4 (cost 1)
B: 1 4 4
________
A: 4 5 5 swap 1 by 5 (cost 1)
B: 1 1 4
________
A: 4 1 5 total cost: 2
B: 5 1 4
So the question we do at every swap is this. Is it better to swap directly or swapping twice using the minimum element as pivot?
In a nutshell, let m be the minimum element in both arrays and you want to swap i for j. The cost of the swap will be
min( min(i,j), 2 * m )
So just find out all the swaps you need to do, apply this formula and sum the results to get your answer.
#user1745866 You can simplify your task of determining the answer -1 by using only variable:
let we have int x=0 and we will just do XOR of all the i/p integers like this:
int x = 0;
for(int i=0;i<n;i++){
cin>>a[i];
x = x^a[i];
}
for(int i=0;i<n;i++){
cin>>b[i];
x = x^b[i];
}
if(x!=0)
cout<<-1;
else{
...do code for remain 2 condition...
}
Now the point is how it will work because , as all the numbers of both array should occurs only even number of times and when we do XOR operation of any number which occured even number of times we will get 0.... otherwise they can't be identical arrays.
Now for 2nd condition(which gives answer 0) you should use multimap so you would be able to directly compare both arrays in O(n) time complexity as if all elements of both arrays are same you can output:0
(Notice: i am suggesting multimap because 1:You would have both array sorted and all elements would be there means also duplicates.
2: because they are sorted, if they consist of same element at same position we can output:0 otherwise you have to proceed further for your 3rd condition or have to swap the elements.)
For reducing the swap cost see Daniel's answer. For finding if the swap is actually possible, please do the following, the swaps are actually only possible if you have an even number of elements in total, so that you can split them out evenly, so if you have 2, 4 or 6 5's you are good, but if you have 1, 3, or 5 5's return -1. It is impossible if your number of duplicates of a number is odd. For actually solving the problem, there is a very simple solution I can think of, through it is a little bit expensive, you just need to make sure that there are the same number of elements on each side so the simple way to do that would be to declare a new array:
int temp[size of original arrays];
//Go through both arrays and store them in temp
Take half of each element, so something like:
int count[max element in array - min element in array];
for(int i = 0; i < temp.size(); i++){
count[temp[i]]++;
}
Take half of each element from temp. When you see an element that matches a element on your count array so whenever you see a 1 decrement the index on the count array by 1, so something like count[1]--; Assuming count starts at 0. If the index is at zero and the element is that one, that means a swap needs to be done, in this case find the next min in the other array and swap them. Albeit a little bit expensive, but it is the simplest way I can think of. So for example in your case:
i/p:
3 6 6 2
2 7 7 3
o/p :
4
We would need to store the min index as 2. Cause that is the smallest one. So we would have an array that looks like the following:
1 1 0 0 1 1
//one two one three zero four zero five 1 six and 1 seven
You would go through the first array, when you see the second six, your array index at 6 would be zero, so you know you need to swap it, you would find the min in the other array, which is 2 and then swap 6 with 2, after wards you can go through the array smoothly. Finally you go through the second array, afterwards when you see the last 7 it will look for the min on the other side swap them...., which is two, note that if you had 3 twos on one side and one two on the other, chances are the three twos will go to the other side, and 2 of them will come back, because we are always swapping the min, so there will always be an even number of ways we can rearrange the elements.
Problem link https://www.codechef.com/JULY20B/problems/CHFNSWPS
here for calculating minimum number of swap.we will having 2 cases
let say an example
l1=[1,2,2]
l2=[1,5,5]
case 1. swap each pair wrt to min(l1,l2)=1
step 1 swapping single 2 of a pair of 2 from l1-> [1,1,2]
[2,5,5] cost is 1
step 2 swapping single 5 of a pair of 5 from l1-> [1,5,2]
[2,1,5] cost is 1
total cost is 2
case 2. swap min of l1 with max of l2(repeat until both list end)
try to think if we sort 1st list in increasing order and other as decreasing order then we can minimize cost.
l1=[1,2,2]
l2=[5,5,1]
Trick is that we only need to store min(l1,l2) in variable say mn. Then remove all common element from both list.
now list became l1=[2,2]
l2=[5,5]
then swap each element from index 0 to len(l1)-1 with jump of 2 like 0,2,4,6..... because each odd neighbour wiil be same as previous number.
after perform swapping cost will be 2 and
l1=[5,2]
l2=[2,5] cost is 2
total cost is 2
Let say an other example
l1=[2,2,5,5]
l2=[3,3,4,4]
after solving wrt to min(l1,l2) total cost will be 2+2+2=6
but cost after sorting list will be swap of ((2,4) and (5,3)) is 2+3=5
so minimum swap to make list identical is min(5,6)=5
//code
l1.sort()
l2.sort(reverse=True)
sums=0
for i in range(len(l1)):
sums+=min(min(l1[i],l2[i]),2*minimum))
print(sums)
#print -1 if u get odd count of a key in total (means sums of count of key in both list)

How to find un-ordered numbers (lineal search)

A list partially ordered of n numbers is given and I have to find those numbers that does not follow the order (just find them and count them).
There are no repeated numbers.
There are no negative numbers.
MAX = 100000 is the capacity of the list.
n, the number of elements in the list, is given by the user.
Example of two lists:
1 2 5 6 3
1 6 2 9 7 4 8 10 13
For the first list the output is 2 since 5 and 6 should be both after 3, they are unordered; for the second the output is 3 since 6, 9 and 7 are out of order.
The most important condition in this problem: do the searching in a linear way O(n) or being quadratic the worst case.
Here is part of the code I developed (however it is no valid since it is a quadratic search).
"unordered" function compares each element of the array with the one given by "minimal" function; if it finds one bigger than the minimal, that element is unordered.
int unordered (int A[MAX], int n)
int cont = 0;
for (int i = 0; i < n-1; i++){
if (A[i] > minimal(A, n, i+1)){
count++;
}
}
return count;
"minimal" function takes the minimal of all the elements in the list between the one which is being compared in "unordered" function and the last of the list. i < elements <= n . Then, it is returned to be compared.
int minimal (int A[MAX], int n, int index)
int i, minimal = 99999999;
for (i = index; i < n; i++){
if (A[i] <= minimo)
minimal = A[i];
}
return minimal;
How can I do it more efficiently?
Start on the left of the list and compare the current number you see with the next one. Whenever the next is smaller than the current remove the current number from the list and count one up. After removing a number at index 'n' set your current number to index 'n-1' and go on.
Because you remove at most 'n' numbers from the list and compare the remaining in order, this Algorithmus in O(n).
I hope this helps. I must admit though that the task of finding numbers that are out of of order isn't all that clear.
If O(n) space is no problem, you can first do a linear run (backwards) over the array and save the minimal value so far in another array. Instead of calling minimal you can then look up the minimum value in O(1) and your approach works in O(n).
Something like this:
int min[MAX]; //or: int *min = new int[n];
min[n-1] = A[n-1];
for(int i = n-2; i >= 0; --i)
min[i] = min(A[i], min[i+1]);
Can be done in O(1) space if you do the first loop backwards because then you only need to remember the current minimum.
Others have suggested some great answers, but I have an extra way you can think of this problem. Using a stack.
Here's how it helps: Push the leftmost element in the array onto the stack. Keep doing this until the element you are currently at (on the array) is less than top of the stack. While it is, pop elements and increment your counter. Stop when it is greater than top of the stack and push it in. In the end, when all array elements are processed you'll get the count of those that are out of order.
Sample run: 1 5 6 3 7 4 10
Step 1: Stack => 1
Step 2: Stack => 1 5
Step 3: Stack => 1 5 6
Step 4: Now we see 3 is in. While 3 is less than top of stack, pop and increment counter. We get: Stack=> 1 3 -- Count = 2
Step 5: Stack => 1 3 7
Step 6: We got 4 now. Repeat same logic. We get: Stack => 1 3 4 -- Count = 3
Step 7: Stack => 1 3 4 10 -- Count = 3. And we're done.
This should be O(N) for time and space. Correct me if I'm wrong.

Lowest Common Ancestor Optimization

I have a rudimentary array with elements [0 to N - 1] where each element is a structure that has an index always pointing to a location earlier in the array.
At one point, as part of a much larger algorithm, I want to find a specific C lowest common ancestor between the node X and any nodes after.
int LCA(a, b) {
while (a != b) {
if (a > b) {
a = nodes[a].parent;
} else {
b = nodes[b].parent;
}
}
return a;
}
for (y = x + 1; y < n; ++y) {
if (LCA(x, y) == c) {
//other code
}
}
The above code is really pseudo-code. I've managed to slightly improve performance of LCA() by having a look-up table generated as it is used. Something like this:
int LCA(a, b) {
if (lookup[a, b]) {
return lookup[a, b];
}
oa = a; ob = b;
while (a != b) {
if (a > b) {
a = nodes[a].parent;
} else {
b = nodes[b].parent;
}
}
lookup[oa, ob] = a;
lookup[ob, oa] = a;
return a;
}
I know there's likely a way I can make some sort of specialized LCA() function, that is, replace all of the above code in some manner to specialize it so it's considerably faster. But I've not thought of anything interesting.
I've attempted to see if I could simply do an LCA check between C and Y by seeing if LCA(c, y) == LCA(x, y), but of course that was not accurate.
To re-cap: X is always less than Y. C is always less than X (and thus Y). Parents are always at a lower index than their children (so it is ordered).
Would nodes knowing their depth help at all?
This code accounts for 80% of CPU time of the entire algorithm that takes about 4 minutes in total. A solution to this would easily improve the algorithm as a whole. Thanks!
The LCA of x and y will be the node with smallest height between an occurrence of x and an occurrence of y in the euler tour (*) of your tree. To find this in O(1) time, you need to solve the RMQ problem using this method.
(*): your tour needs a slight modification for this to work. You must append a value to your array each time you get back to it (return from a recursive call to a child) as well. For the wiki tree, it would look like this:
1 2 3 4 5 6 7 8 9 10 11
1 2 6 2 4 2 1 3 1 5 1
Note that there's no point to have leafs show up twice (although it wouldn't affect correctness).
So, for example, RMQ(2, 5) will be the node with minimum height out of these:
2 3 4 5 6 7 8 9 10
2 6 2 4 2 1 3 1 5
Which is node 1.
That is not the only valid interval you can take. It's also valid to take the last occurrence of 2:
6 7 8 9 10
2 1 3 1 5
This will also return 1 as the LCA.
This way, you can answer LCA queries in constant time with linear time spent on preprocessing.

Make QuickSort sort by multiple criteria?

Is there anyway to make a quicksort sort by multiple conditions? For example, I have a set of edges. Each edge has a source, destination, and length. I want to put the edge with a smaller length in my array first. But if the lengths are the same, I want to sort by that with a smaller source vertex. If these source vertexes are the same, I want to sort by the smaller of the two destination vertices.
For example:
4 (source) 2 (destination) 3 (length)
1 (source) 5 (destination) 3 (length)
Since they both have the same length, we look at the source vertex. Since the second edge is smaller than the first edge, we swap them because we compare by source vertex.
Below is my quicksort and I'm honestly not sure why it's not sorting correctly.If there's a way to make quicksort less efficient but more stable, I would gladly take suggestions!
void quickSort(edge *e, int left, int right)
{
int i = left, j = right;
int temp, temp1, temp2;
int pivot = (left + right)/2;
while(i <= j)
{
while(e[i] < e[pivot])
i++;
while(e[pivot] < e[j])
j--;
if(i <= j)
{
temp = e[i].getLength();
temp1 = e[i].getEdgeSrc();
temp2 = e[i].getEdgeDes();
e[i].setLength(e[j].getLength());
e[i].setEdgeSrc(e[j].getEdgeSrc());
e[i].setEdgeDes(e[j].getEdgeDes());
e[j].setLength(temp);
e[j].setEdgeSrc(temp1);
e[j].setEdgeDes(temp2);
i++;
j--;
} //if statement
}///while loop
if(left < j)
quickSort(e, left, j);
if(i < right)
quickSort(e, i, right);
}
My sorting of conditions:
bool edge::operator<(const edge &other) const
{
if (length < other.length)
return true;
else if ((length == other.length) && (source < other.source))
return true;
else if((length == other.length) && (source == other.source) && (destination < other.destination))
return true;
return false;
}
Again, if anyone knows a way to make this quicksort correctly by reducing the time complexity of it but making it stable, I would gladly take any suggestions! Thank you! Any help?
Edit: This is how I invoked my quicksort. I invoked it based on the number of edges read.
quickSort(e, 0, edges-1); //-1 because if you put in edges, it'd go past the bounds of the array
EDIT: when I try to put in something like this in my algorithm:
0 1 1
0 3 1
1 3 1
2 5 1
4 10 1
4 8 1
10 8 1
11 6 2
11 7 2
6 7 1
9 6 1
9 7 1
This is the output:
0 1 1
0 3 1
1 3 1
2 5 1
4 8 1
4 10 1
6 7 1
6 9 1
8 10 1 <- should be below 7 9 1
7 9 1 <- should be above 8 10 1
6 11 2
7 11 2
It is cleaner to write it this way
if (length != other.length)
return length<other.length;
if ( source != other.source)
return source < other.source;
return destination < other.destination;
You should also be able to do temp = e[i] and so on since the members are all ints.
This (and the code you submitted) should do the task you want I think.
If you are having stability issues, thats because quicksort isnt stable. You could get around it by adding more conditions so that lhs==rhs doesnt happen. Alternatively you can try Mergesort
I dont have much experience with Quick sort frankly, but your impl does look markedly different from Wikipedias In Place Algorithm. For instance, your pivot is not moved at all. Could you check if that is the problem?
Edit
After looking at your link
It looks like the algorithm linked also uses pivot as a value instead of as an index (as you do). It looks syntactically identical to yours until you consider that your pivot value might move, after which your pivot index would point to something else
int pivot = arr[(left + right) / 2];
Does this help?
EDIT: Here's pseudocode for in-place quicksort: http://en.wikipedia.org/wiki/Quicksort#In-place_version
This differs from your code in that the pivot is a value (an average of the left and right values) rather than an index.
If you're looking for a simple non-optimal solution, mergesort the entire list by destination vertex, then mergesort the entire list by origin vertex, then mergesort the entire list by edge length. This takes advantage of the fact that mergesort is a stable sort algorithm and has running time O(E) on the number of edges.

Interview: Summing numbers in two linked lists

During an interview yesterday, I was asked how I would go about summing the values of two singly linked lists that contained digits. They also said the lists could be unequal lengths.
I asked if the list was stored backwards, as that's how I learned about it at uni, but they said no, it was stored forward. They also said I couldn't simply reverse the lists, add then, then reverse it to get it forward again because that option required too much processing. This sort of solution is all I've been able to find online.
I was unable to give an answer, even after they hinted that I should be doing this with a recursive function.
Can anyone help me out with what the solution would have been. This was for a C++ job and I'm hoping that if I ever get called back and I'm able to explain I researched the solution, they might see that as a good sign. Thank you.
For those confused about how the summation is supposed to work, it was presented in this way.
List 1: 1->2->9
List 2: 1->3
So since the numbers are stored forward, I would need to begin by adding the 9 and 3 (end of both lists). Then take the 1 carry and do 1 + 2 + 1. Etc.
You count the length of both lists. You pad at the beginning the shorter list with a number of 0 digits so that they are equal in length. Now you pad both numbers with an extra 0 (it will be used by the carry of the first digits. So that it's possible that 9 + 1 = 10).
You create a third linked list of length equal to the previous two.
Now you do a class like this:
class Digit
{
public:
Digit *Next;
int Dt;
}
and a function like this:
int Sum(const Digit* left, const Digit* right, Digit* runningTotal)
{
int carry = 0;
if (left->Next != NULL)
{
carry = Sum(left->Next, right->Next, runningTotal->Next);
}
carry += left->Dt + right->Dt;
runningTotal->Dt = carry % 10;
carry /= 10;
return carry;
}
This is "version 0".
In "version 1" you remove the extra padding for the last carry and you add it only if needed.
In "version 2" you remove unnecessary "0" digits from the front of the linked lists.
In "version 3" you create the runningTotal linked list directly in Sum. You give to the first level Sum only the "Head" of the Running Total.
In "version 4" instead of padding the shorter LL, you pass a parameter on the number of digits to skip from the longest LL (this is the most difficult passage).
There is another possibility, much more complex, but that doesn't require to pre-count the length of the lists. It uses two recursive functions:
The first recursive function simply traverses left and right while both are present. If both finishes at the same time then you can simply roll-back as in the previous example.
If one of them finishes before the other, then you use another recursive function like this (the initial value of *extraDigits is 1):
void SaveRemainingDigits(const Digit *remaining, int *extraDigits, int **buffer)
{
int currentDigit = *extraDigits - 1;
*extraDigits = *extraDigits + 1;
if (remaining->Next)
{
SaveRemainingDigits(remaining->Next, extraDigits, buffer);
}
else
{
*buffer = (int*)malloc(sizeof(int) * extraDigits);
}
(*buffer)[currentDigit] = remaining->Dt;
}
when this function finally returns, we have a scratchpad from where to extract the digits and the length of the scratchpad
The innermost level of our first recursive function has now to sum its current digit of the shortest linked list with the last digit of the scratchpad and put the current digit of the longest linked list in the scratchpad in place of the digit just used. Now you unroll your recursive function and you use the scratchpad as a circular array. When you finish unrolling, then you add elements to the runningTotal linked list taking them directly from the scratchpad.
As I've said, it's a little complex, but in 1-2 hours I could write it down as a program.
An example (without carry)
1 2 3 4
6 5
you recurse the first two elements. So you have
1-6 (in the first level)
2-5 (in the second level)
Now you see that the second list is finished and you use the second function.
3 (extraDigit enters as 0, is modified to 1. currentDigit = 0)
4 (extraDigit enters as 1, is modified to 2. currentDigit = 1.
malloc of 2 elements,
buffer[currentDigit] = 4 => buffer[1] = 4)
unroll and we return to the previous row
3 (currentDigit = 0
buffer[currentDigit] = 3 => buffer[0] = 3)
Now we return to the previous function
2-5 (in the second level,
with a lengthBuffer == 2,
we set index = length(buffer) - 1
currentDigitTotal = 5 + buffer[index] => currentDigitTotal = 5 + 4
buffer[index] = 2 => buffer[1] = 2;
index = (index - 1 + lengthBuffer) % lengthBuffer => index = 0
1-6 (in the first level,
with a lengthBuffer == 2,
index = 0,
currentDigitTotal = 6 + buffer[index] => currentDigitTotal = 6 + 3
buffer[index] = 1 => buffer[0] = 1;
index = (index - 1 + lengthBuffer) % lengthBuffer => index = 1
now we exited the recursive function.
In an external function we see that we have a buffer.
We add its elements to the head of the total.
Our Linked list now is 9-9 and our buffer is 1,2 with index 1
for (int i = 0; i < lengthBuffer; i++)
{
runningTotal.AddHead(buffer(index));
index = (index - 1 + lengthBuffer) % lengthBuffer
}
I will approach this problem in something like this
Let's suppose the 2 lists are :
1->2->7->6->4->3 and
5->7->2
The sum is 1->2->7 + Sum(6->4->3, 5->7->2)
Now we make a function that take 2 lists of same size and returns their sum
which will be something like
list1->val + list2->val + Sum(list1->next, list2->next)
with base case if(list1->next == NULL) return list1->val+list2->val;
Note :: we can handle the carry in next pass easily or you can handle that in our sum function itself
So after all this our ans will be 1->2->7->11->11->5
then recursively do %10 and take carry and add it to previous value.
so final ans will be 1->2->8->2->1->5
I would have created a node like *head or *tail to store the address of the node that I started from, then iterate through the list making sure im not back at my start point. This doesn't require to to have to count the length of each, which sounds inefficient.
As for the recursiveness just do this check at the top of the function and return (node->value + myfunct(node->prev)); It'd be more efficient given you're doing the math once.
The lists "1, 2, 9" and "1, 3" each represent the numbers "129" and "13", in which case the sum is "142".
Using recursion
Compute the length of each list.
If the lengths differ, pad the shortest with zeroes at the beggining.
Iterate over the lists recursively, returning: a) the carry number if any, or zero otherwise, and b) the tail of the list.
In pseudocode:
def sum_lists_rec(a, b, start_a, start_b, length_a, length_b):
"""Returns a pair of two elements: carry and the tail of the list."""
if the end of the lists:
return (0, empty_list)
result = sum_lists_rec(a+1, b+1, start_a+1, start_b+1, length_a, length_b)
carry = (a[0] + b[0] + result[0]) / 10
digit = (a[0] + b[0] + result[0]) % 10
return (carry, [digit] ++ result[1])
def sum_lists1(a, b):
length_a = length(a)
length_b = length(b)
if length_a < length_b:
a = [0, 0, ..., (length_b - length_a)] ++ a
else if length_b < length_a:
b = [0, 0, ..., (length_a - length_b)] ++ b
result = sum_lists_rec(a, b, length_a, length_b, 0, 0)
if result[0] != 0:
return [result[0]] ++ result[1]
else:
return result[1]
As an alternative, you can use a stack:
Compute the length of each list.
If the lengths differ, pad the shortest with zeroes at the beggining.
Push each digit of both lists on the stack.
Pop the stack until is empty, creating the new list.