how to look for a specific difference between two numbers in multiple numbers - difference

I am trying to identify a specific difference between two numbers in a list of multiple numbers. For example, if I have a list 1, 3, 23, 66, 45, 73 I want to look for a difference of 20.

Here is an algorithm to find all pairs whose difference is D.
Let N be the list of numbers where N[i] is the i'th number in the list for i = 1 to M.
Sort N in increasing order.
Keep track of two indexes i and j on N.
Set i = 1, j = 1.
For each i, increment j until either N[i] + D = N[j] or j is maximum without N[i] + D getting greater than N[j]. If N[i] + D = N[j] then a pair (N[i] N[j]) has been found. Continue with next i.

Related

two pairs with same max sum in c

Given an array a[].Find the two pairs (a,b) and (c,d) such that a+b==c+d.And the sum (a+b==c+d)value as maximum as possible we just have to print that sum value if it is forming the two pairs with same sum value else -1
Note->NO cpp only c language allowed which makes this problem more difficult for me
Example: N = 6, S[] = { 2, 3, 6, 4, 1, 5 } You can select pair of (6, 3) and (5, 4), two numbers can be same ,but same number can not be part of both pair.
My Thinking 1 -> I tried to make all possible pairs store the pairs sum in sorted array ,then i started searching form end to check if it is possible that we can find two teams with maxsum But unable to handle like case 0 0 1 1(which contain duplicates)
My Thinking 2 ->all ways to choose 1st, 2nd and 3rd student and check whether you have 4th one with skill equal to (S1+S2−S3)? And then choose maximum among all possible teams. But since n<=500 it will be O(n^4) can give TLE.
please help!
Let's use pairs (a, b) as being:
a: the index of a number in the array
b: the index of other number in the array (a != b)
Let's create a dictionary D to store lists of those pairs. If a pair (a, b) is such that S[a] + S[b] = 10, then (a, b) should be included in the list D[S[a] + S[b]].
That means that the key to find a pair in D is the sum of both elements represented by this pair in the original array.
If another pair (c, d) also satisfies S[c] + S[d] = 10, then (c, d) would be in the same list D[S[a] + S[b]].
We can iterate through the array and save all pairs in their correct lists:
for(int i = 0; i < |S| - 1; i++){
for(int j = i + 1; j < |S|; j++){
D[S[i] + S[j]].Add( new pair(i, j) );
}
}
With your dictionary filled, you have a lot of lists of pairs whose sum (in the original array) is the same. For each key k (that represents a sum), ask if the length of the list D[k] is at least 2, which means there are at least 2 pairs holding that same sum. If it is, search for a two pairs in the list that don't have anyone in common, this will be your answer. Search from the biggest key to the smallest for better performance. This approach is O(n²).
A straightforward algorithm:
1) Find all two-sized subset of the array and their sums (n(n-1)/2)
2) Now, sort these \Theta(n^2) numbers in \Theta(n^2 log(n))
3) Then traverse this list in descending order two find duplicates
4) This duplicate value in sums could be reported as a result
Hence, the problem could be solved in \Theta(n^2 log(n)).

Sum of continuous sequences

Given an array A with N elements, I want to find the sum of minimum elements in all the possible contiguous sub-sequences of A. I know if N is small we can look for all possible sub sequences but as N is upto 10^5 what can be best way to find this sum?
Example: Let N=3 and A[1,2,3] then ans is 10 as Possible contiguous sub sequences {(1),(2),(3),(1,2),(1,2,3),(2,3)} so Sum of minimum elements = 1 + 2 + 3 + 1 + 1 + 2 = 10
Let's fix one element(a[i]). We want to know the position of the rightmost element smaller than this one located to the left from i(L). We also need to know the position of the leftmost element smaller than this one located to the right from i(R).
If we know L and R, we should add (i - L) * (R - i) * a[i] to the answer.
It is possible to precompute L and R for all i in linear time using a stack. Pseudo code:
s = new Stack
L = new int[n]
fill(L, -1)
for i <- 0 ... n - 1:
while !s.isEmpty() && s.top().first > a[i]:
s.pop()
if !s.isEmpty():
L[i] = s.top().second
s.push(pair(a[i], i))
We can reverse the array and run the same algorithm to find R.
How to deal with equal elements? Let's assume that a[i] is a pair <a[i], i>. All elements are distinct now.
The time complexity is O(n).
Here is a full pseudo code(I assume that int can hold any integer value here, you should
choose a feasible type to avoid an overflow in a real code. I also assume that all elements are distinct):
int[] getLeftSmallerElementPositions(int[] a):
s = new Stack
L = new int[n]
fill(L, -1)
for i <- 0 ... n - 1:
while !s.isEmpty() && s.top().first > a[i]:
s.pop()
if !s.isEmpty():
L[i] = s.top().second
s.push(pair(a[i], i))
return L
int[] getRightSmallerElementPositions(int[] a):
R = getLeftSmallerElementPositions(reversed(a))
for i <- 0 ... n - 1:
R[i] = n - 1 - R[i]
return reversed(R)
int findSum(int[] a):
L = getLeftSmallerElementPositions(a)
R = getRightSmallerElementPositions(a)
int res = 0
for i <- 0 ... n - 1:
res += (i - L[i]) * (R[i] - i) * a[i]
return res
If the list is sorted, you can consider all subsets for size 1, then 2, then 3, to N. The algorithm is initially somewhat inefficient, but an optimized version is below. Here's some pseudocode.
let A = {1, 2, 3}
let total_sum = 0
for set_size <- 1 to N
total_sum += sum(A[1:N-(set_size-1)])
First, sets with one element:{{1}, {2}, {3}}: sum each of the elements.
Then, sets of two element {{1, 2}, {2, 3}}: sum each element but the last.
Then, sets of three elements {{1, 2, 3}}: sum each element but the last two.
But this algorithm is inefficient. To optimize to O(n), multiply each ith element by N-i and sum (indexing from zero here). The intuition is that the first element is the minimum of N sets, the second element is the minimum of N-1 sets, etc.
I know it's not a python question, but sometimes code helps:
A = [1, 2, 3]
# This is [3, 2, 1]
scale = range(len(A), 0, -1)
# Take the element-wise product of the vectors, and sum
sum(a*b for (a,b) in zip(A, scale))
# Or just use the dot product
np.dot(A, scale)

Find largest continuous sum such that the minimum of it and it's complement is largest

I'm given a sequence of numbers a_1,a_2,...,a_n. It's sum is S=a_1+a_2+...+a_n and I need to find a subsequence a_i,...,a_j such that min(S-(a_i+...+a_j),a_i+...+a_j) is the largest possible (both sums must be non-empty).
Example:
1,2,3,4,5 the sequence is 3,4, because then min(S-(a_i+...+a_j),a_i+...+a_j)=min(8,7)=7 (and it's the largest possible which can be checked for other subsequences).
I tried to do this the hard way.
I load all values into the array tab[n].
I do this n-1 times tab[i]+=tab[i-j]. So that tab[j] is the sum from the beginning till j.
I check all possible sums a_i+...+a_j=tab[j]-tab[i-1] and substract it from the sum, take the minimum and see if it's larger than before.
It takes O(n^2). This makes me very sad and miserable. Is there a better way?
Seems like this can be done in O(n) time.
Compute the sum S. The ideal subsequence sum is the longest one which gets closest to S/2.
Start with i=j=0 and increase j until sum(a_i..a_j) and sum(a_i..a_{j+1}) are as close as possible to S/2. Note which ever is closer and save the values of i_best,j_best,sum_best.
Increment i and then increase j again until sum(a_i..a_j) and sum(a_i..a_{j+1}) are as close as possible to S/2. Note which ever is closer and replace the values of i_best,j_best,sum_best if they are better. Repeat this step until done.
Note that both i and j are never decremented, so they are changed a total of at most O(n) times. Since all other operations take only constant time, this results in an O(n) runtime for the entire algorithm.
Let's first do some clarifications.
A subsequence of a sequence is actually a subset of the indices of the sequence. Haivng said that, and specifically int he case where you sequence has distinct elements, your problem will reduce to the famous Partition problem, which is known to be NP-complete. If that is the case, you can manage to solve the problem in O(Sn) where "n" is the number of elements and "S" is the total sum. This is not polynomial time as "S" can be arbitrarily large.
So lets consider the case with a contiguous subsequence. You need to observe array elements twice. First run sums them up into some "S". In the second run you carefully adjust array length. Lets assume you know that a[i] + a[i + 1] + ... + a[j] > S / 2. Then you let i = i + 1 to reduce the sum. Conversely, if it was smaller, you would increase j.
This code runs in O(n).
Python code:
from math import fabs
a = [1, 2, 3, 4, 5]
i = 0
j = 0
S = sum(a)
s = 0
while s + a[j] <= S / 2:
s = s + a[j]
j = j + 1
s = s + a[j]
best_case = (i, j)
best_difference = fabs(S / 2 - s)
while True:
if fabs(S / 2 - s) < best_difference:
best_case = (i, j)
best_difference = fabs(S / 2 - s)
if s > S / 2:
s -= a[i]
i += 1
else:
j += 1
if j == len(a):
break
s += a[j]
print best_case
i = best_case[0]
j = best_case[1]
print "Best subarray = ", a[i:j + 1]
print "Best sum = " , sum(a[i:j + 1])

Minimum sum that cant be obtained from a set

Given a set S of positive integers whose elements need not to be distinct i need to find minimal non-negative sum that cant be obtained from any subset of the given set.
Example : if S = {1, 1, 3, 7}, we can get 0 as (S' = {}), 1 as (S' = {1}), 2 as (S' = {1, 1}), 3 as (S' = {3}), 4 as (S' = {1, 3}), 5 as (S' = {1, 1, 3}), but we can't get 6.
Now we are given one array A, consisting of N positive integers. Their are M queries,each consist of two integers Li and Ri describe i'th query: we need to find this Sum that cant be obtained from array elements ={A[Li], A[Li+1], ..., A[Ri-1], A[Ri]} .
I know to find it by a brute force approach to be done in O(2^n). But given 1 ≤ N, M ≤ 100,000.This cant be done .
So is their any effective approach to do it.
Concept
Suppose we had an array of bool representing which numbers so far haven't been found (by way of summing).
For each number n we encounter in the ordered (increasing values) subset of S, we do the following:
For each existing True value at position i in numbers, we set numbers[i + n] to True
We set numbers[n] to True
With this sort of a sieve, we would mark all the found numbers as True, and iterating through the array when the algorithm finishes would find us the minimum unobtainable sum.
Refinement
Obviously, we can't have a solution like this because the array would have to be infinite in order to work for all sets of numbers.
The concept could be improved by making a few observations. With an input of 1, 1, 3, the array becomes (in sequence):
(numbers represent true values)
An important observation can be made:
(3) For each next number, if the previous numbers had already been found it will be added to all those numbers. This implies that if there were no gaps before a number, there will be no gaps after that number has been processed.
For the next input of 7 we can assert that:
(4) Since the input set is ordered, there will be no number less than 7
(5) If there is no number less than 7, then 6 cannot be obtained
We can come to a conclusion that:
(6) the first gap represents the minimum unobtainable number.
Algorithm
Because of (3) and (6), we don't actually need the numbers array, we only need a single value, max to represent the maximum number found so far.
This way, if the next number n is greater than max + 1, then a gap would have been made, and max + 1 is the minimum unobtainable number.
Otherwise, max becomes max + n. If we've run through the entire S, the result is max + 1.
Actual code (C#, easily converted to C):
static int Calculate(int[] S)
{
int max = 0;
for (int i = 0; i < S.Length; i++)
{
if (S[i] <= max + 1)
max = max + S[i];
else
return max + 1;
}
return max + 1;
}
Should run pretty fast, since it's obviously linear time (O(n)). Since the input to the function should be sorted, with quicksort this would become O(nlogn). I've managed to get results M = N = 100000 on 8 cores in just under 5 minutes.
With numbers upper limit of 10^9, a radix sort could be used to approximate O(n) time for the sorting, however this would still be way over 2 seconds because of the sheer amount of sorts required.
But, we can use statistical probability of 1 being randomed to eliminate subsets before sorting. On the start, check if 1 exists in S, if not then every query's result is 1 because it cannot be obtained.
Statistically, if we random from 10^9 numbers 10^5 times, we have 99.9% chance of not getting a single 1.
Before each sort, check if that subset contains 1, if not then its result is one.
With this modification, the code runs in 2 miliseconds on my machine. Here's that code on http://pastebin.com/rF6VddTx
This is a variation of the subset-sum problem, which is NP-Complete, but there is a pseudo-polynomial Dynamic Programming solution you can adopt here, based on the recursive formula:
f(S,i) = f(S-arr[i],i-1) OR f(S,i-1)
f(-n,i) = false
f(_,-n) = false
f(0,i) = true
The recursive formula is basically an exhaustive search, each sum can be achieved if you can get it with element i OR without element i.
The dynamic programming is achieved by building a SUM+1 x n+1 table (where SUM is the sum of all elements, and n is the number of elements), and building it bottom-up.
Something like:
table <- SUM+1 x n+1 table
//init:
for each i from 0 to SUM+1:
table[0][i] = true
for each j from 1 to n:
table[j][0] = false
//fill the table:
for each i from 1 to SUM+1:
for each j from 1 to n+1:
if i < arr[j]:
table[i][j] = table[i][j-1]
else:
table[i][j] = table[i-arr[j]][j-1] OR table[i][j-1]
Once you have the table, you need the smallest i such that for all j: table[i][j] = false
Complexity of solution is O(n*SUM), where SUM is the sum of all elements, but note that the algorithm can actually be trimmed after the required number was found, without the need to go on for the next rows, which are un-needed for the solution.

given array A, form array M such that sum of products (a1*m1+...+an*mn) is maximum

I gave an interview recently where I was asked the following algorithmic question. I am not able to come to an O(n) solution nor I was able to find the problem doing google.
Given an array A[a_0 ... a_(n-1)] of integers (+ve and -ve). Form an
array M[m_0 ... m_(n-1)] where m_0 = 2 and m_i in [2,...,m_(i-1)+1]
such that sum of products is maximum i.e. we have to maximize a_0*m_0
+ a_1*m_1 + ... + a_(n-1)*m_(n-1)
Examples
input {1,2,3,-50,4}
output {2,3,4,2,3}
input {1,-1,8,12}
output {2,3,4,5}
My O(n^2) solution was to start with m_0=2 and keep on incrementing by 1 as long as a_i is +ve. If a_i < 0 we have to consider all m_i from 2 to m_i-1 + 1 and see which one produces max sum of products.
Please suggest a linear time algorithm.
Suppose you have the following array:
1, 1, 2, -50, -3, -4, 6, 7, 8.
At each entry, we can either continue with our incrementing progression or reset the value to a lower value.
Here there can be only two good options. Either we would choose the maximum possible value for the current entry or the minimum possible(2). (proof towards the end)
Now it is clear that 1st 3 entries in our output shall be 2, 3 and 4 (because all the numbers so far are positive and there is no reason to reset them to 2 (a low value).
When a negative entry is encountered, compute the sum:
-(50 + 3 + 4) = -57.
Next compute the similar sum for succeeding +ve contiguous numbers.
(6 + 7 + 8) = 21.
Since 57 is greater than 21, it makes sense to reset the 4th entry to 2.
Again compute the sum for negative entries:
-(3 + 4) = -7.
Now 7 is less than 21, hence it makes sense not to reset any further because maximum product shall be obtained if positive values are high.
The output array thus shall be:
2, 3, 4, 2, 3, 4, 5, 6, 7
To make this algorithm work in linear time, you can pre-compute the array of sums that shall be required in computations.
Proof:
When a negative number is encountered, then we can either reset the output value to low value (say j) or continue with our increment (say i).
Say there are k -ve values and m succeeding positive values.
If we reset the value to j, then the value of product for these k -ve values and m +ve values shall be equal to:
- ( (j-2+2)*a1 + (j-2+3)*a2 + ... + (j-2+k+1)*ak ) + ( (j-2+k+2)*b1 + (j-2+k+3)*b2 + ... + (j-2+k+m+1)*am )
If we do not reset the value to 2, then the value of product for these k -ve values and m +ve values shall be equal to:
- ( (i+2)*a1 + (i+3)*a2 + (i+4)*a3 ... + (i+k+1)*ak ) + ( (i+k+2)*b1 + (i+k+3)*b2 + ... + (i+k+m+1)*am )
Hence the difference between the above two expressions is:
(i-j+2)* ( sum of positive values - sum of negative values )
Either this number can be positive or negative. Hence we shall tend to make j either as high as possible (M[i-1]+1) or as low as possible (2).
Pre-computing array of sums in O(N) time
Edited: As pointed out by Evgeny Kluev
Traverse the array backwards.
If a negative element is encountered, ignore it.
If a positive number is encountered, make suffix sum equal to that value.
Keep adding the value of elements to the sum till it remains positive.
Once the sum becomes < 0, note this point. This is the point that separates our decision of resetting to 2 and continuing with increment.
Ignore all negative values again till you reach a positive value.
Keep repeating till end of array is reached.
Note: While computing the suffix sum, if we encounter a zero value, then there can be multiple such solutions.
Thanks to Abhishek Bansal and Evgeny Kluevfor for the pseudo-code.
Here is the code in Java.
public static void problem(int[] a, int[] m) {
int[] sum = new int[a.length];
if(a[a.length-1] > 0)
sum[a.length-1] = a[a.length-1];
for(int i=a.length-2; i >=0; i--) {
if(sum[i+1] == 0 && a[i] <= 0) continue;
if(sum[i+1] + a[i] > 0) sum[i] = sum[i+1] + a[i];
}
//System.out.println(Arrays.toString(sum));
m[0] = 2;
for(int i=1; i < a.length; i++) {
if(sum[i] > 0) {
m[i] = m[i-1]+1;
} else {
m[i] = 2;
}
}
}

Resources