5

Given a sorted array[1..n] where each element ranging from 1 to 2n. Is there a way to find triplet whose sum is given integer x. I know O(n^2) solution. Is there any algorithm better than n^2 ones.

Chandan
  • 277
  • 4
  • 14
  • Related: [Sum-subset with a fixed subset size](http://stackoverflow.com/q/8916539/572670) – amit Feb 15 '15 at 14:38
  • Based on some quick googling, it looks like it can be done in O(n + n log n) time: http://en.wikipedia.org/wiki/3SUM#Non-zero_sum – Noyo Feb 15 '15 at 14:39
  • what's the O(n^2) solution? – thang Feb 15 '15 at 14:43
  • @thang : http://en.wikipedia.org/wiki/3SUM#Quadratic_algorithm – Noyo Feb 15 '15 at 14:47
  • @Noyo, oh that's pretty cool. I guess for r-sum, it's O(n^(r/2) log n) for r even and it's O(n^((r+1)/2)) for r odd. This using these tricks. I think the absolute theoretical lower bound for 3sum is something like O(n^1.5 (log n)^.5). This is by computing the # of compares required to uniquely locate a triplet. – thang Feb 15 '15 at 15:03

2 Answers2

5

It is possible to achieve an O(n log n) time complexity using that fact the maximum value of each element is O(n).

  1. For each 1 <= y <= 4 * n, let's find the number of pairs of elements that sum up to y. We can create a polynomial of 2 * n power, where the i-th coefficient of this polynomial is the number of occurrences of the number i in the given array. Now we can find the square(I'll call it s) of this polynomial in O(n log n) time using Fourier's Fast Transform. The i-th coefficient of s is exactly the number of pairs of elements that sum up to i.

  2. Now we can iterate over the given array. Let's assume that the current element is a. Then we just need to check the number of pairs that sum up to X - a. We have already done it in the step 1).

If all triplets must consist of different elements, we need to subtract the number of such triplets that sum up to X but contain duplicates. We can do it in O(n log n) time, too(for triplets that consist of three equal elements, we just need to subtract the number of occurrences of X / 3 in the given array. For triplets with one duplicate, we can just iterate over the element that is repeated twice(a) and subtract the number of occurrences of X - 2 * a).

If we need to find a triplet itself, not just count them, we can do the following:

  1. Count the number of triplets and pairs as suggested above.

  2. Find such an element that there is a pair that sums up to X with it.

  3. Find two elements that sum up to the desired sum of this pair.

All these steps can be accomplished in linear time(using the fact that all sums are O(n)).

kraskevich
  • 17,514
  • 3
  • 26
  • 42
  • Hi your first step is unclear. Can you please provide with simple example. – Chandan Feb 15 '15 at 16:33
  • @ChandanParameswaraiah Let's assume that have an array {1, 1, 2}. The polynomial is {0, 2, 1}. Now we just should multiply it by itself. – kraskevich Feb 15 '15 at 17:02
  • Hi Please don mind. I am finding it difficult. Say if I have an Array {1,2,3,8,10} and x is 11. I have to find the triplet (here it is 1,2,8). Can you illustrate this algorithm on this example. – Chandan Feb 15 '15 at 18:00
1

Your problem is apparently the non-zero sum variant of the 3SUM problem.

Because you know the possible range of the integers beforehand, you can achieve lower bounds than the general case, according to the second paragraph of the article:

When the elements are integers in the range [-N, ..., N], 3SUM can be solved in O(n + N log N) time by representing the input set S as a bit vector, computing the set S + S of all pairwise sums as a discrete convolution using the Fast Fourier transform, and finally comparing this set to -S.

In your case, you would have to pre-process the array by subtracting n + X/3 before running the algorithm.

One thing to note is that the algorithm assumes you're working with a set of numbers, and I'm not sure what (if any) implications there may be on running time if your array may include duplicates.

Noyo
  • 4,234
  • 3
  • 34
  • 40
  • The problem is that if you have an array of 10 integers from MININT to MAXINT, then your run time is MAXINT log MAXINT, which is worse than brute force force of 1000. I guess the original post does say 2n range, so this is not an issue. – thang Feb 15 '15 at 15:10