Sum of all subparts of an array of integers - arrays

Given an array {1,3,5,7}, its subparts are defined as {1357,135,137,157,357,13,15,17,35,37,57,1,3,5,7}.
I have to find the sum of all these numbers in the new array. In this case sum comes out to be 2333.
Please help me find a solution in O(n). My O(n^2) solution times out.
link to the problem is here or here.
My current attempt( at finding a pattern) is
for(I=0 to len) //len is length of the array
{
for(j=0 to len-i)
{
sum+= arr[I]*pow(10,j)*((len-i) C i)*pow(2,i)
}
}
In words - len-i C i = (number of integers to right) C weight. (combinations {from permutation and combination})
2^i = 2 power (number of integers to left)
Thanks

You can easily solve this problem with a simple recursive.
def F(arr):
if len(arr) == 1:
return (arr[0], 1)
else:
r = F(arr[:-1])
return (11 * r[0] + (r[1] + 1) * arr[-1], 2 * r[1] + 1)
So, how does it work? It is simple. Let say we want to compute the sum of all subpart of {1,3,5,7}. Let assume that we know the number of combinatiton of {1,3,5} and the sum of subpart of {1,3,5} and we can easily compute the {1,3,5,7} using the following formula:
SUM_SUBPART({1,3,5,7}) = 11 * SUM_SUBPART({1,3,5}) + NUMBER_COMBINATION({1,3,5}) * 7 + 7
This formula can easily be derived by observing. Let say we have all combination of {1,3,5}
A = [135, 13, 15, 35, 1, 3, 5]
We can easily create a list of {1,3,5,7} by
A = [135, 13, 15, 35, 1, 3, 5] +
[135 * 10 + 7,
13 * 10 + 7,
15 * 10 + 7,
35 * 10 + 7,
1 * 10 + 7,
3 * 10 + 7,
5 * 10 + 7] + [7]

Well, you could look at at the subparts as sums of numbers:
1357 = 1000*1 + 100*3 + 10*5 + 1*7
135 = 100*1 + 10*3 + 1*5
137 = 100*1 + 10*3 + 1*7
etc..
So, all you need to do is sum up the numbers you have, and then according to the number of items work out what is the multiplier:
Two numbers [x, y]:
[x, y, 10x+y, 10y+x]
=> your multiplier is 1 + 10 + 1 = 12
Three numbers [x, y, z]:
[x, y, z,
10x+y, 10x+z,
10y+x, 10y+z,
10z+x, 10z+y,
100x+10y+z, 100x10z+y
.
. ]
=> you multiplier is 1+10+10+1+1+100+100+10+10+1+1=245
You can easily work out the equation for n numbers....

If you expand invisal's recursive solution you get this explicit formula:
subpart sum = sum for k=0 to N-1: 11^(N-k) * 2^k * a[k]
This suggests the following O(n) algorithm:
multiplier = 1
for k from 0 to N-1:
a[k] = a[k]*multiplier
multiplier = multiplier*2
multiplier = 1
sum = 0
for k from N-1 to 0:
sum = sum + a[k]*multiplier
multiplier = multiplier*11
Multiplication and addition should be done modulo M of course.

Related

Given an array of `first n` natural numbers with one element missing and one duplicate element. Figure out both numbers [duplicate]

This question already has answers here:
Find the missing and duplicate elements in an array in linear time and constant space
(8 answers)
Closed 4 years ago.
Given an array of first n natural numbers with one element missing and one duplicate element. figure out both numbers. I was asked this question in one of the interviews.
For example, the sample array is
5, 2, 1, 4, 5
where n=5
Answer for the given array should be:
missing element = 3
duplicate element = 5
Is it possible to come-up with the solution without iterating the array.
I was able to come-up with a solution having complexity O(nlogn), without extra space. Does any O(n) solution exist (without extra space)?
Let's say that you have numbers 1,...,n. Now, denote their sum 1 + 2 + ... + n as S. If we denote the missing number as j and the duplicit one as k, we will get for the modified sum S' = S - j + k, so that's one equation for two variables. We can repeat the same procedure, but this time, summing second powers, thus S_2 = 1 + 4 + ... + n^2. For the sequence with one missing and one duplicit number, the result will be S_2' = S_2 - j*j + k*k. Thus we get two equations for two variables.
In total, we have:
S' = S - j + k
S_2' = S_2 - j*j + k*k
therefore
k - j = S' - S =: a
k*k - j*j = S_2' - S_2 =: b
where we introduced the symbols a and b to simplify the notation.
Now, k*k - j*j = (k - j)*(k + j), thus:
k - j = a
k*k - j*j = a * (k + j) = b
summing both equations gives:
2*k = b/a + a
2*j = b/a - a
For your particular example:
S = 1 + 2 + 3 + 4 + 5 = 15
S_2 = 1 + 4 + 9 + 16 + 25 = 55
For the series with one missing and one duplicit element:
S' = 5 + 2 + 1 + 4 + 5 = 17
S_2' = 25 + 4 + 1 + 16 + 25 = 71
then:
a = S' - S = 2
b = S_2' - S_2 = 16
therefore:
2*k = 8 + 2 = 10
2*j = 8 - 2 = 6
which gives:
k = 5, j = 3
In practice (as noted by #HermanTheGermanHesse), one can obtain closed-form expressions for S as well as S_2 in terms of polynomials in n (so-called Faulhaber's formulae), namely: S = n*(n+1)/2 and S_2 = n*(n+1)*(2*n+1)/6. Therefore it is just sufficient to go once over the input data, accumulate S' and S_2', and use the formulae for k and j given above...

Return all possible permutations and combinations of numbers from n arrays whose sum is less than m and greater than r

I have two arrays:
array1: [0 1 2 3]
array2: [0 1 2 3 4 5 6 7]
array3: [0 1 2 3 4 5]
I want to find combination from each array like 1 element from each array such that the sum >= m eg.3 and sum <=r eg. 6
Example:
array1 array2 array3 elements
1 1 1 (sum is 3)
1 5 0 (sum is 6)
1 6 1 (wrong result sum is greater than 6)
Thanks in advance.
I don't understand how to solve this problem . A pseudocode will be very helpful.
As I have mentioned in my comment; compared to the brute force, in JS by a dynamical programming approach you may get the results much faster, like in total around 10ms for your test case, as follows;
function getCombos(arr,n,m){
function getBinaryMap(d){
return Array(a.length).fill()
.reduce((p,c,i) => p.concat(d >> i & 1),[]);
}
var a = arr.reduce((p,c) => p.concat(c.filter(e => e !== 0 && e <= m)),[]);
t = [0],
r = [];
a.forEach(e => t = t.concat(t.map((f,i) => (f + e >= n && f + e <= m && r.push(getBinaryMap(t.length + i)), f + e))));
return r.map(e => e.reduce((p,c,i) => c ? p.concat(a[i]) : p,[]));;
}
var arrays = [[0, 1, 2, 3],[0, 1, 2, 3, 4, 5, 6, 7],[0, 1, 2, 3, 4, 5]];
result = getCombos(arrays,3,6);
console.log(JSON.stringify(result));
Let there be N=3 sorted arrays A(size = p), B(size = q) and C(size=r).
Choose a number say X and try finding a sum of N=3 numbers x1 + x2 + x3
such that X = x1 + x2 + x3. Finding x1, x2 and x3 can be done using dynamic programming.
Now,
Consider the sequence ABC and use binary search to find x1 in array A, x2 in array B and x3 in array C.
Consider the sequence ACB and use binary search to find x1 in array A, x2 in array C and x3 in array B.
Consider the sequence BAC and use binary search to find x1 in array B, x2 in array A and x3 in array C.
You will find that there are N! number of such sequences.
You will be required to repeat the above process for all X such that [m]<=[X]<=[r].
Total Complexity would be (r - m + 1) * (N!) * ((log p) + (log q) + (log r)).
Total Complexity does not include the dynamic programming part.

Given 3 sorted arrays A, B, C and number S, find i, j, k such that A[i] + B[j] + C[k] = S

I've just found out how to solve this in O(n^2 log n) time (assuming each array has the same length):
for each A[i]:
for each B[j]:
if A[i] + B[j] + C.binarySearch(S - A[i] - B[j]) == S:
return (i, j, k)
Is there any way to solve this in O(n^2) time or to improve the above algorithm?
The algorithm you have ain't bad. Relative to n^2, log(n) grows so slowly that it can practically be considered a constant. For example, for n = 1000000, n^2 = 1000000000000 and log(n) = 20. Once n becomes large enough for log(n) to have any significant influence, n^2 will already be so big that the result cannot be computed anyway.
A solution, inspired by #YvesDaoust, though I'm not sure if it's exactly the same:
For every A[i], calculate the remainder R = S - A[i] which should be a combination of some B[j] and C[k];
Let j = 0 and k = |C|-1 (the last index in C);
If B[j] + C[k] < R, increase j;
If B[j] + C[k] > R, decrease k;
Repeat the two previous steps until B[j] + C[k] = R or j >= |B| or k < 0
I suggest not to complicate the algorithm too much with micro-optimizations. For any reasonably small set of numbers and it will be fast enough. If the arrays become too large for this approach, your problem would make a good candidate for Machine Learning approaches such as Hill Climbing.
if the arrays are of non-negatives
* you can trim all 3 arrays to at S => A[n] > S
* similarly, dont bother checking array C if A[aIdx] + B[bIdx] > S
prepare:
sort each array ascending +O(N.log(n))
implement binary search on each array ?O(log(N))
compute:
i=bin_search(smallest i that A[i]+B[0]+C[0]>=S); for (;i<Na;i++) { if (A[i]+B[0]+C[0]>S) break;
j=bin_search(smallest j that A[i]+B[j]+C[0]>=S); for (;j<Nb;j++) { if (A[i]+B[j]+C[0]>S) break;
ss=S-A[i]-B[j];
if (ss<0) break;
k=bin_search(ss);
if (k found) return; // found solution is: i,j,k
}
}
if I see it right and: N=max(Na,Nb,Nc), M=max(valid intervals A,B,C) ... M<=N
it is (3*N.log(N)+log(N)+M*log(N)*M*log(N)) -> O((M^2)*log(N))
the j binary search can be called just once and then iterate +1 if needed
the complexity is the same but the N has changed
for average conditions is this much much faster because M<<N
The O(N²) solution is very simple.
First consider the case of two arrays, finding A[i] + B[j] = S'.
This can be rewritten as A[i] = S' - B[j] = B'[j]: you need to find equal values in two sorted arrays. This is readily done in linear time with a merging process. (You can explicitly compute the array B' but this is unnecessary, just do it on the fly: instead of fetching B'[j], get S' - B[NB-1-j]).
Having established this procedure, it suffices to use it for all elements of C, in search of S - C[k].
Here is Python code that does that and reports all solutions. (It has been rewritten to be compact and symmetric.)
for k in range(NC):
# Find S - C[k] in top-to-tail merged A and B
i, j= 0, NB - 1
while i < NA and 0 <= j:
if A[i] + B[j] + C[k] < S:
# Move forward A
i+= 1
elif A[i] + B[j] + C[k] > S:
# Move back B
j-= 1
else:
# Found
print A[i] + B[j] + C[k], "=", A[i], "+", B[j], "+", C[k]
i+= 1; j-= 1
Execution with
A= [1, 2, 3, 4, 5, 6, 7]; NA= len(A)
B= [2, 3, 5, 7, 11]; NB= len(B)
C= [1, 1, 2, 3, 5, 7]; NC= len(C)
S= 15
gives
15 = 3 + 11 + 1
15 = 7 + 7 + 1
15 = 3 + 11 + 1
15 = 7 + 7 + 1
15 = 2 + 11 + 2
15 = 6 + 7 + 2
15 = 1 + 11 + 3
15 = 5 + 7 + 3
15 = 7 + 5 + 3
15 = 3 + 7 + 5
15 = 5 + 5 + 5
15 = 7 + 3 + 5
15 = 1 + 7 + 7
15 = 3 + 5 + 7
15 = 5 + 3 + 7
15 = 6 + 2 + 7

A case of a making-change (sort of). Find the minimal composition of weights

TLDR: (part 1) Need to print out the best composition of weights to reach a target weight. (part 2) Don't know what approach to choose. (part 3) Also, recursion is not my friend.
I am not asking for a solution, I am just looking for a direction.
PART 1
Some text first.
The input to the program is:
a number of weights
weights themselves
target weights I am supposed to compose
There always has to be a weight that = 1, so all the weights can be composed exactly.
I am supposed to print out the optimal composition of weights, for example
number of weights: 4
weights: 1, 3, 7, 10
target weight: 4
output: 2 x 7
PART 2
The first thing that came to my mind was the unbounded knapsack problem, where I would set all the values for weights to "1" and then I'd look for the lowest possible value in the knapsack. The problem is, my programming skills don't reach that level and my googling skills failed me when I wanted to find a fine article/code/video/whatever to understand it.
Then someone pointed out the making-change problem. The problem there is that it usually uses an array and I am expecting really large numbers, I cannot afford to alloc an array of size = target weight. Also, it seems to require quite a lot of magic if I want not only the lowest possible number of weights, but the exact counts.
My solution now, shall I?
sort the weights in descending order
count the number of weights yielded from the greedy algorithm
remove one biggest weight used and try to compose the weight without it
repeat 3 until I have removed all the "biggest weights" or the number of weights started to grow again
(for weights = 1, 3, 7, 10 and target = 14, greedy would give me 1 x 10 + 1 x 3 + 1 x 1, after the third step I would get (0 x 10 +) 2 x 7)
I got here. Only I need to repeat this not outside the recursive function (like I was doing until I realised it still doesn't give me the right results) but I need to move the loop into the recursive function.
PART 3
This is how parts of my code looks now:
for ( i = 0; i < weights_cnt; i ++ )
for ( j = 0; j <= weight / *(weights + i); j ++ )
{
*counter = 0;
if ( (res = greedyMagicImproved(weights + i, weight / *(weights + i) - j, weight, counter, min)) == 0 || min > *counter ) break;
else min = *counter;
}
It's a mess, I know. (the first recursive function I've ever written, sorry for that)
int greedyMagicImproved (int * weights, int limit, int weight, int * counter, int min)
{
if ( *counter > min ) return 0;
else if ( weight % *weights == 0 )
{
printf ("%d * %d\n", limit, *weights);
*counter += limit;
return *counter;
}
else if ( weight == 0 ) return *counter;
else if ( weight / *weights )
{
printf ("%d * %d + ", limit, *weights);
*counter += limit;
return (greedyMagicImproved(weights + 1, (weight - *weights * limit) / *(weights + 1), (weight - *weights * limit) % *weights, counter, min));
}
else return greedyMagicImproved(weights + 1, weight / *(weights + 1), weight, counter, min);
}
This one produces something like this:
Number of weights:
8
Actual weights of weights:
1 2 4 5 10 20 60 95
Weights to be composed:
124
GREEDY = 1 * 95 + 1 * 20 + 1 * 5 + 1 * 4
IMP = 1 * 95 + 1 * 20 + 1 * 5 + 1 * 4
2 * 60 + 1 * 4
6 * 20 + 1 * 4
... some more irrelevant results I'll deal with later
28
GREEDY = 1 * 20 + 1 * 5 + 1 * 2 + 1 * 1
IMP = 1 * 20 + 1 * 5 + 1 * 2 + 1 * 1
1 * 20 + 1 * 5 + 1 * 2 + 1 * 1
1 * 20 + 1 * 5 + 1 * 2 + 1 * 1
2 * 10 + 1 * 5 + 1 * 2 + 1 * 1
5 * 5 + 1 * 2 + 1 * 1
... some more results as well
While I get to see the correct result in the first case, I do not in the second.
So basically, my question is: Should I try to move the loop part into the recursion (and write it basically all over again because I have no idea how to do it) or should I go stealing/packing and making change?
Here is a DP formulation:
Let w[i], i=0,1,...p be the coin weights and f(t,i) be the number of coins needed to hit target t using only w[k], k >= i. When there is no possible way to make change, then f(t,i) is infinite. With this we know
f(t,i) = min_{n} [ n + f(t - n * w[i], i + 1) ]
In English, to hit the target with the minimum of coins using only coins i, i+1, ... p, choose all possible quantities n of coin i and then use the same DP to make change for the remaining amount using only coins i+1,i+2,..., finally choosing the solution that produced the minimum.
The base cases are common sense. For example f(0,_) = 0. You don't need any coins to hit a target of zero.
If T is the problem target, then the answer will be f(T,0).
Since you don't want the answer, I'll let you convert this to code. It's likely you'll get to answers faster if the weights are sorted in descending order.

Find the given sum "total" from the three matrixes algorithm

i was following the this question and i felt that this can be solved in O(NLogN). Below is my algorithm:
1. Sort list1 , list2, list3 i.e. O(NLogN)
2. while indexA < size and indexB < size and indexC < size //here size is the array size
int sum = a1[indexA] + a2[indexB] + a3[indexC]
if sum < total then choose the minimum value from a1, a2, a3 and increment that index
if sum > total print total can not be found and return
if sum == total then print the indexes
//this is O(N)
Hence all total O(NLogN).
Please tell me about the correctness of the above algo.
EDIT
As Muckle_ewe has explained that this algo will fail in some places so there is no point in further discussing on the algo rather please comment whether the question can be solvable in O(NLogN) if so then algo, thanks?
No that would fail on the
if sum < total then choose the minimum value from a1, a2, a3 and increment that index
line. Consider the following counter example (pseudocode)
list1 = [1, 10]
list2 = [2, 3]
list3 = [3, 4]
Let total be 7, for which the solution would be 1 + 2 + 4 (or 1 + 3 + 3). Let indexA = indexB = indexC = 0. Initial sum is then
list1[0] + list2[0] + list3[0]
1 + 2 + 3 = 6
As this is less than 7, we increase the index which gave the smallest list value, which was indexA as list1[indexA] = 1. Sum is then
list1[1] + list2[0] + list3[0]
10 + 2 + 3 = 15
As this is greater than 7 your algorithm tells us there is no solution

Resources