Find the minimum set of integers whose sum is greater than a given integer - arrays

I am attempting to solve the below question. I solved this question in O(n^2) time complexity. Is there a way to optimize it further and bring the complexity down to O(n) by iterating the array just once?
Given an array of n integers and a number S. I need to find the minimum set of consecutive integers whose sum is greater than the number S. If no such set exists, I will print 0.
Required complexities:
Space complexity-O(1)
Time Complexity-O(n)
Example-
Array A={2,5,4,6,3,9,2,17,1}
S= 17
Output=2
Explanation-
Possible solutions are:-
{2,5,4,6,3}=2+5+4+6+3=20(>18)=5 numbers
{5,4,6,3,9}=27(>18)=5 numbers
{4,6,3,9}=22(>18)-4 numbers
{6,3,9,2}=20=4 numbers
{3,9,2,17}=4 numbers
{9,2,17}=3 numbers
{2,17}=2 numbers
so, minimum =2 numbers. output=2.

Assuming that all integers are non-negative and S is positive, you can use the following algorithm:
Use two indices, one for where the current sequence starts, and another for where it ends. When the sum of that sequence is too small you extend the sequence by incrementing the second index; if the sum is over S, you keep track of whether it is the best so far and at the same time remove the first value from the sequence, by incrementing the first index.
Here is the algorithm in more formal pseudo code:
n = size(A)
best = n + 1
sum = 0
i = 0
for j = 0 to n - 1:
sum = sum + A[j]
while sum > S:
if j - i + 1 < best:
best = j - i + 1
sum = sum - A[i]
i = i + 1
if best > n:
best = 0
output best
Space complexity is O(1) as there are 4 numerical variables involved (not counting the input array), which represents a fixed amount of memory.
Time complexity is O(n) as the total number of times the statements in the inner loop execute is never more than n (i is incremented each time and will never bypass j).

Related

Finding smallest number N, having k trailing zeroes in factorial of N

I got a problem about finding the smallest N, where N! contains exactly k trailing zeros.
I've got an idea of finding it through binary search from here - Finding natural numbers having n Trailing Zeroes in Factorial .
Is it possible to calculate it without binary search, using any formula or some iterations?
You can use the formula that the number of times p divides n! is:
k = floor(n/p) + floor(n/p^2) + floor(n/p^3) + ...
Combining this with the fact that the number of trailing zeros is exactly equal to the number of times 5 evenly divides it (each zero corresponds to a 2 and 5 pair, but given 2 is less than 5, we'll always have more 2s than 5s, and thus be constrained by our 5s).
With some algebra, and applying the formula for an infinite geometric series, we can get a very (very!) close lower bound on n. We then just increment n by 5 as much as necessary get the actual result. In practice, this ends up being 1-2 increments for k in the lower thousands, so its fairly negligible.
Full code below:
def count_div5(n):
result = 0
pow5 = 5
while pow5 <= n:
result += n // pow5
pow5 *= 5
return result
def n_from_fact_zeros(k):
n = round(4*k)
n += -n % 5
while count_div5(n) < k:
n += 5
return n

Need help in Algorithms - Finding the outputted maximum sum

I'm currently studying algorithms and I was curious about a homework problem (yeah.. I know) that I have been finding conflicting answers on.
In pseudocode the algorithm is:
Algorithm-1(A:array[1..n] of integer) sum,max:integer
sum = 0
max = 0
for i = 1 to n
sum = 0
for j = i to n
sum = sum + A[j]
if sum > max then
max = sum
return max
Given the array, [-1,2,-3,4,-5,6,7,-8,9,-10] I found that the max value that the above function returns should be 4 based on my interpretation of the algorithm, but online the only two answers I've found are 14 and 10.
My understanding of this algorithm is that it takes the base array, finds its sum, and then takes the same array starting at the next index and finds that sum, and the value that's returned is the highest of these sums.
Basically if given the array of [1,2,-3,4,5] it looks at it this way:
Sum of [1,2,-3,4,5] = 9
Sum of [2,-3,4,5] = 8
Sum of [-3,4,5] = 6
Sum of [4,5] = 9
Sum of [5] = 5
And the final max value returned is 9 since 9 > 8 > 6 > 5
Based on this understanding, I'm thinking that the value of my array is 4 from the [6,7,-8,9,-10] sub array. Would that be correct?
Nope, I suppose you are not understanding the concept of subarrays, Subarrays are basically any set of contiguous elements in an array. Let's take your example.
For
[-1,-2,-3,4,-5,6,7,-8,9,-10]
For every array of size N, there are N*(N+1)/2 Subarrays. The answer in this particular case is the subarray [6,7,-8,9] which returns the sum as 14.
Have a look at the below link for better understanding:
Kadane Algorithm for maximum sum subarray

While loop time complexity O(logn)

I cannot understand why the time complexity for this code is O(logn):
double n;
/* ... */
while (n>1) {
n*=0.999;
}
At least it says so in my study materials.
Imagine if the code were as follows:
double n;
/* ... */
while (n>1) {
n*=0.5;
}
It should be intuitive to see how this is O(logn), I hope.
When you multiply by 0.999 instead, it becomes slower by a constant factor, but of course the complexity is still written as O(logn)
You want to calculate how many iterations you need before n becomes equal to (or less than) 1.
If you call the number of iterations for k you want to solve
n * 0.999^k = 1
It goes like this
n * 0.999^k = 1
0.999^k = 1/n
log(0.999^k) = log(1/n)
k * log(0.999) = -log(n)
k = -log(n)/log(0.999)
k = (-1/log(0.999)) * log(n)
For big-O we only care about "the big picture" so we throw away constants. Here log(0.999) is a negative constant so (-1/log(0.999)) is a positive constant that we can "throw away", i.e. set to 1. So we get:
k ~ log(n)
So the code is O(logn)
From this you can also notice that the value of the constant (i.e. 0.999 in your example) doesn't matter for the big-O calculation. All constant values greater than 0 and less than 1 will result in O(logn).
Logarithm has two inputs: a base and a number. The result of a logarithm is the power you need to raise the base to to achieve the given number. Since your base is 0.999, the number is the first smaller than 1 and you have a scalar, which is n, effectively the number of steps depends on the power you need to raise your base to achieve such a small number, which multiplied with n will yield a smaller number than 1. This corresponds to the definition of the logarithm, with which I have started my answer.
EDIT:
Think about it this way: You have n as an input and you search for the first k where
n * .999^k < 1
since you are searching k by incrementing it, since if you have l >= n at a step, then you will have l * .999 in the next step. Repeating this achieves a logarithmic complexity for your multiplication algorithm.

Finding continuous subsequence that minimizes the average of the rest of the array?

Suppose there's an integer array arr[0..n-1]. Find a subsequence sub[i..j] (i > 0 and j < n - 1) such that the rest of the array has the smallest average.
Example:
arr[5] = {5,1,7,8,2};
Remove {7,8}, the array becomes {5, 1, 2} which has average 2.67 (smallest possible).
I thought this is a modification of the Longest Increasing Subsequence but couldn't figure it out.
Thanks,
Let's find the average value using binary search.
Suppose, that sum of all elements is S.
For given x let's check if exist i and j such that avg of all elements except from i to j less or equal to x.
To do that, let's subtract x from all elements in arr. We need to check if exists i and j such that sum of all elements except from i to j less or equal to zero. To do that, lets find sum of all elements in current array: S' = S - x * n. So we want to find i and j such that sum from i to j will be greater or equal than S'. To do that, let's find subarray with the larges sum. And this can be done using elegant Jay Kadane's algorithm: https://en.wikipedia.org/wiki/Maximum_subarray_problem
When to terminate binary search? When the maximum subarray sum will be zero (or close enough).
Time complexity: O(n log w), w - presicion of the binary search.

Finding the maximum element of the array is a divisor of another element

Given an array of non-zero integers of length N. Write a function that returns the maximum element of the array, which is a divisor of some other element of the same array. If this number is not present, then return 0. I know how to solve in O(n^2). Is it possible to do it faster?
First, note that you are assuming that testing if integer A divides integer B can be completed in O(1). I guess you're also assuming that no pre-computation (e.g. building a divisibility graph) is allowed.
Since integer factorization (for which no polynomial algorithm is known) is not an option, you can't do faster then O(n^2) (worst case).
For example, given the input {11,127, 16139} (all integers are primes, each integer squared is less than the next one), you can't avoid checking all pairs.
I have been playing with your problem for a while and found a sometimes-better than brute-force solution.
It is based in to ideas:
We can perform the search in an order such that bigger divisor candidates are tested first. That way we can terminate the search as soon as we find a divisor.
One way to test if some candidate divw is a divisor for number w, is to calculate r = floor(w / divw) and then check that r * divw == w. The interesting thing, is that when it fails, we can calculate a top limit for the next divisor candidate of w as topw = floor(w / (r + 1)). So we can discard anything between divw and topw.
A sample for that second point: Imagine we are testing if divw = 10 is a divisor of w = 12, we calculate r = floor(12 / 10) = 1, and topw = floor(w / 2) = 6. So, we don't need to check if numbers in the set between 7 and 9, inclusive, are divisors for 12.
In order to implement this algorithm I have used a heap to keep the numbers in the set using as key the next divisor candidate that has to be tested.
So...
Initialize the heap pushing every element which its predecessor as its bigger potential divisor.
Pop the first element from the heap (w) and check if the potential divisor candidate (divw) is actually a divisor.
If it is, return it as the biggest divisor
Calculate topw for w, divw; search the next element in the set divw' that is equal or lesser than topw (using binary-search); if found, push w,divw' again in the queue.
unless the queue is empty, goto 2.
An implementation in Common Lisp is available here!
I guess calculating the theoretical computational cost for this algorithm would be challenging, specially for the average case, so I am not going to do it!
After running it a dozen times, it seems to behave better than the brute force approach when N is high and the numbers are dispersed (which means that the probability of one number being a divisor of other is low). On the other hand, brute-force seems to be faster when N is low or when the numbers are densely distributed in a small range (which means that the probability of a number being a divisor of other is high).
I did it so
int f(int* a, int size)
{
int max = 0;
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
if (a[i] > a[j] && a[i] % a[j] == 0 && a[j] > max)
max = a[j];
return max;
}

Resources