5

So say I have a sorted array:

{ 1, 2, 3, 4, 5, 6 }

And I want to see if there exists three elements that sum to 14.

3 + 5 + 6 = 14

I'm pretty sure there is no way to do this in O(N) time, but I think it can be done in O(N^2) somehow.

Nikunj Banka
  • 10,091
  • 15
  • 68
  • 105

4 Answers4

5

This problem is similar to the 3SUM problem and it can done in O(N^2) . This java working code accomplishes this.

    // The function prints the values if there exists 3 distinct indices
    // in the array arr that sum to req.
    void run(){
        int[] arr = { 1, 2, 3, 4, 5, 6 };
        int req = 14;

        // For the algorithm to work correctly, the array must be sorted
        Arrays.sort(arr);      

        for(int i=0; i<arr.length; i++){// Iterate over the elements of the array.

            // Check in linear time whether there exists distinct indices 
            // lo and hi that sum to req-arr[i]
            int lo=0, hi = arr.length-1;
            boolean found = false;
            while(lo<hi){
                if(lo==i){
                    lo++;
                    continue;
                }
                if(hi==i){
                    hi--;
                    continue;
                }
                int val = arr[lo] + arr[hi] + arr[i];
                if(val == req){
                    System.out.println(arr[lo] + " + " + arr[hi] + " + " + arr[i] + " = " + req);
                    found = true;
                    break;
                }else if(val < req){
                    lo++;
                }else{
                    hi--;
                }
            }
            if(found)break;
        }
    }
Nikunj Banka
  • 10,091
  • 15
  • 68
  • 105
2

In Computational theory, this is known as 3sum problem. Best solution for this problem found so far costs O(N^2). It is still an open question whether this can be solved with better cost. You can find one implementation of this algorithm here.

Mohit Jain
  • 29,414
  • 8
  • 65
  • 93
0

This is similar to Subset Sum Problem, which is NP-Complete.
But limiting the subset length to 3, it is possible to find a fast solution.
Your problem is equivalent to the 3SUM problem.
r = K as in your question .

Pseudocode : O(N^2)

for (i in 1..n-2) 
{
  j = i+1  // Start right after i.
  k = n    // Start at the end of the array.

  while (k >= j) {
    // done.
    if (A[i] + A[j] + A[k] == r) return (A[i], A[j], A[k])

    // We didn't match. Let's try to get a little closer:
    //   If the sum was too big, decrement k.
    //   If the sum was too small, increment j.
    (A[i] + A[j] + A[k] > r) ? k-- : j++
  }
  // When the while-loop finishes, j and k have passed each other and there's
  // no more useful combinations that we can try with this i.
}
Aseem Goyal
  • 2,516
  • 2
  • 25
  • 43
0

If k is about the same as the size of the array (or smaller) and all of the numbers are positive (dealing with zeros is trivial), you can use DP efficiently. For all numbers from 0 to k, you remember whether it can be obtained using zero, one, two or three integers from the array. The solution is O(Nk) in time and O(k) in space and is very easy to implement.

int[] myarray = {1, 2, 3, 4, 5, 6};
int k = 14;

int[] dp = new int[k+1];
dp[0] = 1;
for (int i = 0; i < myarray.length; ++i) {
    for (int j = k; j >= myarray[i]; --j) {
        dp[j] |= dp[j-myarray[i]] << 1;
    }
}
if ((dp[k] & 8) > 0) {
    System.out.println("YES");
} else {
    System.out.println("NO");
}
Danstahr
  • 3,902
  • 17
  • 34