Find pair/triplets whose sum is least away from the given value - arrays

There are 2 variations of this question.
Given 2 arrays of integers, select single element from each array so that their sum is least away (numerically) from given integer value V. Sum can be greater than V.
Given 3 arrays of integers, select single element from each array so that their sum is least away (numerically) from given integer value V. Sum can be greater than V.
I know there is a naive O(n^2) and O(n^3) solution respectively for them and I'd like to ask if there's any approach which optimises running time.

For the first case, you could sort both the arrays in O(nlogn), and then for each element x in the first array, find V-x in the second array using the binary-search/upper-bound algorithm.
Its total complexity would still be O(nlogn) which is less than O(n*n).
For the second case, you can apply a similar algorithm with O(n*n*log(n)) complexity.

Related

Find all possible combination of subarrays in a larger int array based on a given pattern

Given an int array of only 1's and 0's like [1,0,0,1,0,0,0,1], I want to get all possible sub arrays which will start and end with 1.
Like in this case the output will be this three arrays :
[1,0,0,1]
[1,0,0,0,1]
[1,0,0,1,0,0,0,1]
This are all three possible combinations.
I have done it with O(n^2) time complexity but I want more efficient solution.
Which algorithm would suffice for this case? I am using java for implementation.
If you just want to find the number of arrays which start and end with 1, then it can be solved by a simple formula.
The problem reduces to the solution i.e. to Number of ways to select any 2 indices of 1's in the given array.
Now that can be given by formula : N(N-1)/2, where N is the number of 1's in the given array.
So you will have to traverse the whole array at least once. Therefore time complexity is reduced to O(Size of Array) ~ O(n).

Find way to separate array so each subarrays sum is less or equal to a number

I have a mathematical/algorithmic problem here.
Given an array of numbers, find a way to separate it to 5 subarrays, so that sum of each subarrays is less than or equal to a given number. All numbers from the initial array, must go to one of the subarrays, and be part of one sum.
So the input to the algorithm would be:
d - representing the number that each subarrays sum has to be less or equal
A - representing the array of numbers that will be separated to different subarrays, and will be part of one sum
Algorithm complexity must be polynomial.
Thank you.
If by "subarray" you mean "subset" as opposed to "contiguous slice", it is impossible to find a polynomial time algorithm for this problem (unless P = NP). The Partition Problem is to partition a list of numbers into to sets such that the sum of both sets are equal. It is known to be NP-complete. The partition problem can be reduced to your problem as follows:
Suppose that x1, ..., x_n are positive numbers that you want to partition into 2 sets such that their sums are equal. Let d be this common sum (which would be the sum of the xi divided by 2). extend x_i to an array, A, of size n+3 by adding three copies of d. Clearly the only way to partition A into 5 subarrays so that the sum of each is less than or equal to d is if the sum of each actually equals d. This would in turn require 3 of the subarrays to have length 1, each consisting of the number d. The remaining 2 subarrays would be exactly a partition of the original n numbers.
On the other hand, if there are additional constraints on what the numbers are and/or the subarrays need to be, there might be a polynomial solution. But, if so, you should clearly spell out what there constraints are.
Set up of the problem:
d : the upper bound for the subarray
A : the initial array
Assuming A is not sorted.
(Heuristic)
Algorithm:
1.Sort A in ascending order using standard sorting algorithm->O(nlogn)
2.Check if the largest element of A is greater than d ->(constant)
if yes, no solution
if no, continue
3.Sum up all the element in A, denote S. Check if S/5 > d ->O(n)
if yes, no solution
if no, continue
4.Using greedy approach, create a new subarray Asi, add next biggest element aj in the sorted A to Asi so that the sum of Asi does not exceed d. Remove aj from sorted A ->O(n)
repeat step4 until either of the condition satisfied:
I.At creating subarray Asi, there are only 5-i element left
In this case, split the remaining element to individual subarray, done
II. i = 5. There are 5 subarray created.
The algorithm described above is bounded by O(nlogn) therefore in polynomial time.

How to find the smallest difference between two numbers in array without changing the order so that their difference is positive?

I am given a harvest in tons according to the year.
like {3,6,12,1,20,25} .
find the smallest difference in harvest between the harvest of ordered years.
For given example difference is 2 because 3 - 1 = 2. Preserve order and result is positive
Sorting doesn't apply because numbers already sorted according to the years.
One way is to find all positive differences between elments and choose the smallest one.
But it takes O(n^2).
Is there any faster way to do it?
Main task is to find the minimum difference between elements in array without changing the order of elements so that their difference is positive.
According to my understanding of the question, we need to compute min(a[i] - a[j]) among all valid i and j such that i < j and a[i] > a[j].
You can iterate over the array from left to right and keep all elements in a data structure that supports the insert and upper_bound operations efficiently (for example, an std::set in C++ or a TreeSet in Java).
The pseudo code (C++ like) may look like this:
s = empty set
res = INF
for elem in array: // from left to right
if s.upper_bound(elem) != s.end(): // checks if there is a larger element
res = min(res, *s.upper_bound(elem) - elem)
s.insert(elem)
The insert and upper_bound operations take O(log N) time, so the total time complexity is O(N log N).
If you compare every value with every other value, it would be O(n^2).
So a possible answer could be to take the values in an auxillary array, sort it in O(n*ln(n)) and then in one traversal find minimum consecutive differences.
I couldn't figure out a O(n) solution. ( There could be one if some constraints are given on input data).

Finding the smallest positive number in O(nlogn) and O(logn) additional space

This is a slightly modified version of a well known problem, but I can't seem to figure this one out.
We are given an array of size n that contains unsorted sequence of positive numbers with no duplicates. I'm trying to find the smallest positive number that is not contained in the array, but I can't sort or edit the array in any way. The whole thing should be in O(nlogn) time and O(logn) space complexity.
All the solutions I can think of are in polynomial time complexity.
You can solve this without modifying the array by binary searching on the answer. Remember that we are looking for the smallest positive integer that is not in the array. This means the answer can't be larger than n + 1 since we only have n numbers in our array. So we just need to binary search between 1 and n + 1 to find our answer.
Within our binary search, we want to answer the question: for a given number k, is every integer 1 through k contained in our array? Because there are no duplicates, we can solve this by just counting the number of elements in the array less than or equal to k. If the count is k, every such integer is in our array; otherwise, at least one is missing.
So we binary search to find the smallest value of k where the above property is false. The binary search requires O(log n) iterations, and each iteration takes O(n) time for a total of O(n log n) time. The space is actually O(1) since all we need is a single variable for counting.

What is the lowest bound for the algorithm?

Let an algorithm which get unsorted array with the size of n. Let a number k<=n. The algorithm prints the k-smallest numbers from 1 to k (ascending). What is the lower bound for the algorithm (for every k)?
Omega(n)
Omega(k*logn)
Omega(n*logk)
Omega(n*logn)
#1,#2 Are both correct.
Now, from my understanding, if we want to find a lower-bound to an algorithm we need to look at the worst-case. If that the case, then obviously the worst-case is when k=n. We know that sorting an array is bounded by Omega(nlogn) so the right answer is #4.
Unfortunately, I am wrong and the right answer is #5.
Why?
It can be done in O(n + klogk).
Run selection algorithm to find the k smallest element - O(n)
Iterate and return the elements lower/equals k - O(n)
Another iteration might be needed in case of the array allows
duplicates, but it is still done in O(n)
Lastly, you need to sort these elements in O(klogk)
It is easy to see this solution is optimal - cannot get better than O(klogk) factor because otherwise for assigning k=n you could sort any array better, and a linear scan at least is a must to find the required elements to be printed.
Lets try with Linear time:
In order to find the k'th smallest element, we have to use "Randomized-Select" which has the average running time of O(n). And use that element as pivot for the quick sort.
Use Quick sort method to split the array[i] <= k and array[i]>k. This would take O(n) time
Take the unsorted left array[i]<=k (which has k elements) and do counting sort, which will obviously take O(k+K)
Finally the print operation will take O(k)
Total time = O(n)+O(k+K)+O(k) = O(n+k+K)
Here, k is the number of elements which are smaller or equal to K

Resources