Maximum number of subsegments in a circle array - arrays

There are n positive numbers (A1 , ... An) on a circle, how do we divide this circle into subsegments with sum greater or equal to m so that number of subsegments are maximum in O(n) , or O(nlogn)
eg :
n = 6 m = 6
3 1 2 3 6 3
ANS = 3
since we can divide the array into three subsegments{[2,4],[5,5],[6,1]}

If there is at least one number greater or equal to m in the array, just cut the array into smallest possible pieces starting from one of these numbers. Otherwise (and if sum of numbers is at least 2*m) use a pointer-chasing algorithm.
This algorithm uses 2 additional arrays: L for chain lengths (initially zero) and S for starting indices (initially equal to own indices: 0, 1, 2, ...). And 2 array indices: F and B (initially zero).
Increment F while sum between F and B is less than m. Then increment B while sum between F and B is greater than m (but stop when is is still greater or equal to m).
Update arrays: L[F] = 1 + L[B], S[F] = S[B].
Repeat steps 1,2 while F<n. While incrementing F on step 1, copy most recently updated values to L[F] and S[F].
Reset F to zero.
Increment F while sum of elements before F and after B is less than m. Then increment B while sum before F and after B is greater than m (but stop when is is still greater or equal to m).
If F <= S[B] use L[B] + 1 to update maximum number of subsegments.
Repeat steps 5,6 while B<n.

Related

Number of ways to fill an array of size n , such that the mexium is greater than every element of the array?

We have given an empty array of size n , we need to fill it with natural numbers (we are allowed to repeat).
The condition that must follow is the mex of the array must be greater than all the elements we fill in the array .
Can someone pls help me with the number of ways to do so ?
(Different arrangements of same set of numbers are also considered distinct)
PS:- by mex of a sequence I mean the smallest non negative number that doesn't occur in the sequence
Number of such arrays is equivalent to the number of ordered distributions of values 1..N into buckets (so [A],[B,C] and [B,C][A] are distinct ones). And number of such distributions is described by ordered Bell numbers 1,3,13,75....
Example for N=3
1 1 1 //1 permutation
1 1 2 //3 permutations
1 2 2 //3 permutations
1 2 3 //6 permutations
//13 variants
Generation of distributions themselves for reference. Note that for N values every value might fall into part 1..K, where K is in range 1..N, so numbers of parts corresponding to all values form continuous sequence without holes (cf. your mex)
To calculate number of such distributions, we can use recurrence from Wiki, Python code:
def cnk(n, k):
k = min(k, n - k)
if k <= 0:
return 1 if k == 0 else 0
res = 1
for i in range(k):
res = res * (n - i) // (i + 1)
return res
def orderedbell(n):
a = [0]*(n+1)
a[0] = 1
for m in range(1, n+1):
for i in range(1, m+1):
a[m] += cnk(m, i) * a[m - i]
return a[n]
for i in range(1,10):
print(orderedbell(i))
1
3
13
75
541
4683
47293
545835
7087261

Sum of all the elements of 3 different arrays

I want and optimized algorithm to find sum of each and every element of array.
for example let 3 array:
a = [1,2,3,4];
b = [5,6];
c = [8,9];
then final sum will be equal to:
sum(1,5,8)+sum(1,5,9)+sum(1,6,8)+sum(1,6,9)+sum(2,5,8)...+sum(4,6,9)
I tried doing but the algorithm I used had time complexity O(n^3), so I want anything less than this complexity.
Here is my algorithm:
sum = 0
for(i=0;i<a.size();i++)
for(j=0;j<b.size();j++)
for(k=0;k<c.size();k++)
sum = sum+a[i]+b[j]+c[k];
For this example, a, b and c have 4, 2 and 2 elements respectively. If you want to add them in every combination, there will be 4 * 2 * 2 = 16 terms to add. In those terms, each element of a will appear 4 times, because it will be added to 2 * 2 = 4 combinations of elements of b and c. Similarly, each element of b (or c) will appear 8 times, because it will be added to each 4 * 2 = 8 combinations of each elements of a and c (or b).
So, in the final sum, each element of a will appear 4 times and each element of b and c will appear 8 times. Once you figure that out, you can do fewer number of multiplications and additions to get the result.(Just sum of elements of individual arrays and then multiply these sums by 4 , 8 and 8 respectively).
Each element of a will appear in sums with each element of b and each element of c.
This means that every element in a will appear in a number of sums equal to b.length * c.length.
This is also easy to see from the brute force pseudo-code: (modified for readability)
for i = 0 to a.length
for j = 0 to b.length // happens once for each i
for k = 0 to c.length // happens b.length times for each i
sum += a[i] + ... // happens b.length * c.length times for each i
Generalising this, we come up with the following algorithm:
Sum all elements a, multiply the result by b.length * c.length.
Sum all elements b, multiply the result by a.length * b.length.
Sum all elements c, multiply the result by a.length * b.length.
Return the above three values added together.
This is an O(n) algorithm, where n is the total number of elements or average number of elements per array.

Smallest "n" sums from n arrays

I was trying to do my friends problem set from a few years ago to sharpen up my knowledge about data structures etc. I came across this problem, and I'm not really sure where to start. Hopefully someone could help me out!
We are given n unsorted arrays, each array has n elements. Ex.
3 1 2
7 6 9
4 9 12
Now, say we take one element from each array, and add them up. Lets just call the sum of these elements an "n-sum".
I need to devise an algorithm that gives us the n smallest "n-sums" (duplicates are allowed).
In our above ex, the answer would be:
11, 12, 12
# 11 comes from: 1 (first array) + 6 (second array) + 4 (third array)
# 12 comes from: 2 (first array) + 6 (second array) + 4 (third array)
# 12 comes from: 1 (first array) + 7 (second array) + 4 (third array)
One of the suggestions given were to use a priority queue.
Thanks!
The time is at least O (n^2): You must visit all array elements, because if all elements were equal to 1000 except on in each row being 0, you would have to look at the n elements equal to 0, or you couldn't find the smallest sum.
Sort each row, taking O (n^2 log n) steps. In each row, subtract the first element from all elements in the row, so the first element in each row is 0; after you found the smallest sums you can compensate for that. Your example turns into
3 1 2 -> 1 2 3 -> 0 1 2
7 6 9 -> 6 7 9 -> 0 1 3
4 9 12 -> 4 9 12-> 0 5 7
Now finding all sums ≤ K can be done in m steps if there are m sums: In the first row, pick all values in turn as long as they are ≤ K. In the second row, pick all values in turn as long as the sum from two rows is ≤ K and so on. Since each row starts with 0, no time is wasted.
For example, sums ≤ 5 are: 0+0+0, 0+0+5, 0+1+0, 0+3+0, 1+0+0, 1+1+0, 1+3+0, 2+0+0, 2+1+0, 2+3+0. Many more than the three that we needed. If we stop after finding 3 sums ≤ 5, we know very quickly "there are at least 3 sums ≤ 5". We need to have an early stop, because in the general case there could be n^n possible sums.
If you pick K = "largest element in the second column", then you know there are at least n+1 sums with a value ≤ K, because you can pick all 0's, or all 0's except one value from the second column. In your example, K = 5 (we know that worked). Let X be the value where there are n sums ≤ X but fewer than n sums ≤ X - 1. We find X with binary search between 0 and K, and then we find the sums. Example:
K = 5 is known to be big enough. We try K = 2, and find 4 sums (actually we stop at 3 sums). Too many. We try K = 1, and there are three solutions 0+0+0, 0+1+0 and 1+0+0. We try K = 0, but only one solution.
This part goes very quick, so we'd try to reduce the time used for sorting. We notice that in this case looking at the first two columns was enough. We can in each row find the two smallest items, and in this case that would be enough. If the two smallest items are not enough to determine the n smallest sums, find the third smallest item etc. where needed. For example, since the 2nd largest item of the last row is 5, we wouldn't need the third item of the row, because even the 5 is not element of a sum if K ≤ 4.

finding maximum sum of a disjoint sequence of an array

Problem from :
https://www.hackerrank.com/contests/epiccode/challenges/white-falcon-and-sequence.
Visit link for references.
I have a sequence of integers (-10^6 to 10^6) A. I need to choose two contiguous disjoint subsequences of A, let's say x and y, of the same size, n.
After that you will calculate the sum given by ∑x(i)y(n−i+1) (1-indexed)
And I have to choose x and y such that sum is maximised.
Eg:
Input:
12
1 7 4 0 9 4 0 1 8 8 2 4
Output: 120
Where x = {4,0,9,4}
y = {8,8,2,4}
∑x(i)y(n−i+1)=4×4+0×2+9×8+4×8=120
Now, the approach that I was thinking of for this is something in lines of O(n^2) which is as follows:
Initialise two variables l = 0 and r = N-1. Here, N is the size of the array.
Now, for l=0, I will calculate the sum while (l<r) which basically refers to the subsequences that will start from the 0th position in the array. Then, I will increment l and decrement r in order to come up with subsequences that start from the above position + 1 and on the right hand side, start from right-1.
Is there any better approach that I can use? Anything more efficient? I thought of sorting but we cannot sort numbers since that will change the order of the numbers.
To answer the question we first define S(i, j) to be the max sum of multlying the two sub-sequence items, for sub-array A[i...j] when the sub-sequence x starts at position i, and sub-sequence y ends on position j.
For example, if A=[1 7 4 0 9 4 0 1 8 8 2 4], then S(1, 2)=1*7=7 and S(2, 5)=7*9+4*0=63.
The recursive rule to compute S is: S(i, j)=max(0, S(i+1, j-1)+A[i]*A[j]), and the end condition is S(i, j)=0 iff i>=j.
The requested final answer is simply the maximum value of S(i, j) for all combinations of i=1..N, j=1..N, since one of the S(i ,j) values will correspond to the max x,y sub-sequences, and thus will be equal the maximum value for the whole array. The complexity of computing all such S(i, j) values is O(N^2) using dynamic programming, since in the course of computing S(i, j) we will also compute the values of up to N other S(i', j') values, but ultimately each combination will be computed only once.
def max_sum(l):
def _max_sub_sum(i, j):
if m[i][j]==None:
v=0
if i<j:
v=max(0, _max_sub_sum(i+1, j-1)+l[i]*l[j])
m[i][j]=v
return m[i][j]
n=len(l)
m=[[None for i in range(n)] for j in range(n)]
v=0
for i in range(n):
for j in range(i, n):
v=max(v, _max_sub_sum(i, j))
return v
WARNING:
This method assumes the numbers are non-negative so this solution does not answer the poster's actual problem now it has been clarified that negative input values are allowed.
Trick 1
Assuming the numbers are always non-negative, it is always best to make the sequences as wide as possible given the location where they meet.
Trick 2
We can change the sum into a standard convolution by summing over all values of i. This produces twice the desired result (as we get both the product of x with y, and y with x), but we can divide by 2 at the end to get the original answer.
Trick 3
You are now attempting to find the maximum of a convolution of a signal with itself. There is a standard method for doing this which is to use the fast fourier transform. Some libraries will have this built in, e.g. in Scipy there is fftconvolve.
Python code
Note that you don't allow the central value to be reused (e.g. for a sequance 1,3,2 we can't make x 1,3 and y 3,1) so we need to examine alternate values of the convolved output.
We can now compute the answer in Python via:
import scipy.signal
A = [1, 7, 4, 0, 9, 4, 0, 1, 8, 8, 2, 4]
print max(scipy.signal.fftconvolve(A,A)[1::2]) / 2

Smallest number that cannot be formed from sum of numbers from array

This problem was asked to me in Amazon interview -
Given a array of positive integers, you have to find the smallest positive integer that can not be formed from the sum of numbers from array.
Example:
Array:[4 13 2 3 1]
result= 11 { Since 11 was smallest positive number which can not be formed from the given array elements }
What i did was :
sorted the array
calculated the prefix sum
Treverse the sum array and check if next element is less than 1
greater than sum i.e. A[j]<=(sum+1). If not so then answer would
be sum+1
But this was nlog(n) solution.
Interviewer was not satisfied with this and asked a solution in less than O(n log n) time.
There's a beautiful algorithm for solving this problem in time O(n + Sort), where Sort is the amount of time required to sort the input array.
The idea behind the algorithm is to sort the array and then ask the following question: what is the smallest positive integer you cannot make using the first k elements of the array? You then scan forward through the array from left to right, updating your answer to this question, until you find the smallest number you can't make.
Here's how it works. Initially, the smallest number you can't make is 1. Then, going from left to right, do the following:
If the current number is bigger than the smallest number you can't make so far, then you know the smallest number you can't make - it's the one you've got recorded, and you're done.
Otherwise, the current number is less than or equal to the smallest number you can't make. The claim is that you can indeed make this number. Right now, you know the smallest number you can't make with the first k elements of the array (call it candidate) and are now looking at value A[k]. The number candidate - A[k] therefore must be some number that you can indeed make with the first k elements of the array, since otherwise candidate - A[k] would be a smaller number than the smallest number you allegedly can't make with the first k numbers in the array. Moreover, you can make any number in the range candidate to candidate + A[k], inclusive, because you can start with any number in the range from 1 to A[k], inclusive, and then add candidate - 1 to it. Therefore, set candidate to candidate + A[k] and increment k.
In pseudocode:
Sort(A)
candidate = 1
for i from 1 to length(A):
if A[i] > candidate: return candidate
else: candidate = candidate + A[i]
return candidate
Here's a test run on [4, 13, 2, 1, 3]. Sort the array to get [1, 2, 3, 4, 13]. Then, set candidate to 1. We then do the following:
A[1] = 1, candidate = 1:
A[1] ≤ candidate, so set candidate = candidate + A[1] = 2
A[2] = 2, candidate = 2:
A[2] ≤ candidate, so set candidate = candidate + A[2] = 4
A[3] = 3, candidate = 4:
A[3] ≤ candidate, so set candidate = candidate + A[3] = 7
A[4] = 4, candidate = 7:
A[4] ≤ candidate, so set candidate = candidate + A[4] = 11
A[5] = 13, candidate = 11:
A[5] > candidate, so return candidate (11).
So the answer is 11.
The runtime here is O(n + Sort) because outside of sorting, the runtime is O(n). You can clearly sort in O(n log n) time using heapsort, and if you know some upper bound on the numbers you can sort in time O(n log U) (where U is the maximum possible number) by using radix sort. If U is a fixed constant, (say, 109), then radix sort runs in time O(n) and this entire algorithm then runs in time O(n) as well.
Hope this helps!
Use bitvectors to accomplish this in linear time.
Start with an empty bitvector b. Then for each element k in your array, do this:
b = b | b << k | 2^(k-1)
To be clear, the i'th element is set to 1 to represent the number i, and | k is setting the k-th element to 1.
After you finish processing the array, the index of the first zero in b is your answer (counting from the right, starting at 1).
b=0
process 4: b = b | b<<4 | 1000 = 1000
process 13: b = b | b<<13 | 1000000000000 = 10001000000001000
process 2: b = b | b<<2 | 10 = 1010101000000101010
process 3: b = b | b<<3 | 100 = 1011111101000101111110
process 1: b = b | b<<1 | 1 = 11111111111001111111111
First zero: position 11.
Consider all integers in interval [2i .. 2i+1 - 1]. And suppose all integers below 2i can be formed from sum of numbers from given array. Also suppose that we already know C, which is sum of all numbers below 2i. If C >= 2i+1 - 1, every number in this interval may be represented as sum of given numbers. Otherwise we could check if interval [2i .. C + 1] contains any number from given array. And if there is no such number, C + 1 is what we searched for.
Here is a sketch of an algorithm:
For each input number, determine to which interval it belongs, and update corresponding sum: S[int_log(x)] += x.
Compute prefix sum for array S: foreach i: C[i] = C[i-1] + S[i].
Filter array C to keep only entries with values lower than next power of 2.
Scan input array once more and notice which of the intervals [2i .. C + 1] contain at least one input number: i = int_log(x) - 1; B[i] |= (x <= C[i] + 1).
Find first interval that is not filtered out on step #3 and corresponding element of B[] not set on step #4.
If it is not obvious why we can apply step 3, here is the proof. Choose any number between 2i and C, then sequentially subtract from it all the numbers below 2i in decreasing order. Eventually we get either some number less than the last subtracted number or zero. If the result is zero, just add together all the subtracted numbers and we have the representation of chosen number. If the result is non-zero and less than the last subtracted number, this result is also less than 2i, so it is "representable" and none of the subtracted numbers are used for its representation. When we add these subtracted numbers back, we have the representation of chosen number. This also suggests that instead of filtering intervals one by one we could skip several intervals at once by jumping directly to int_log of C.
Time complexity is determined by function int_log(), which is integer logarithm or index of the highest set bit in the number. If our instruction set contains integer logarithm or any its equivalent (count leading zeros, or tricks with floating point numbers), then complexity is O(n). Otherwise we could use some bit hacking to implement int_log() in O(log log U) and obtain O(n * log log U) time complexity. (Here U is largest number in the array).
If step 1 (in addition to updating the sum) will also update minimum value in given range, step 4 is not needed anymore. We could just compare C[i] to Min[i+1]. This means we need only single pass over input array. Or we could apply this algorithm not to array but to a stream of numbers.
Several examples:
Input: [ 4 13 2 3 1] [ 1 2 3 9] [ 1 1 2 9]
int_log: 2 3 1 1 0 0 1 1 3 0 0 1 3
int_log: 0 1 2 3 0 1 2 3 0 1 2 3
S: 1 5 4 13 1 5 0 9 2 2 0 9
C: 1 6 10 23 1 6 6 15 2 4 4 13
filtered(C): n n n n n n n n n n n n
number in
[2^i..C+1]: 2 4 - 2 - - 2 - -
C+1: 11 7 5
For multi-precision input numbers this approach needs O(n * log M) time and O(log M) space. Where M is largest number in the array. The same time is needed just to read all the numbers (and in the worst case we need every bit of them).
Still this result may be improved to O(n * log R) where R is the value found by this algorithm (actually, the output-sensitive variant of it). The only modification needed for this optimization is instead of processing whole numbers at once, process them digit-by-digit: first pass processes the low order bits of each number (like bits 0..63), second pass - next bits (like 64..127), etc. We could ignore all higher-order bits after result is found. Also this decreases space requirements to O(K) numbers, where K is number of bits in machine word.
If you sort the array, it will work for you. Counting sort could've done it in O(n), but if you think in a practically large scenario, range can be pretty high.
Quicksort O(n*logn) will do the work for you:
def smallestPositiveInteger(self, array):
candidate = 1
n = len(array)
array = sorted(array)
for i in range(0, n):
if array[i] <= candidate:
candidate += array[i]
else:
break
return candidate

Resources