MatanBitton
MatanBitton

Reputation: 27

Closest pair sum to x in two sorted arrays

I came across a coding problem that goes as follows:

Given 2 sorted arrays: A and B, and a positive integer x, print the closest pair (one from each array) sum to x.

Example:

B = {10,20,30,40} , A = {0,4,6,11,11} , x = 13.

Output: 4 and 10.

This is what I've tried:

    int i = 0;
    int j = b.length - 1;
    int closest = Integer.MAX_VALUE;
    String s = "";
    while (i <= a.length - 1 && j >= 0)
    {
        if (Math.abs((b[j] + a[i]) - x) < closest || Math.abs((b[j] + a[i]) - x) == 0)
        {
            closest = Math.abs(x - (b[j] + a[i]));
            s = a[i] + " " + "and" + " " + b[j];
            if (j != 0)
                j--;
        }
        if (Math.abs((b[j] + a[i]) - x) > closest || j == 0)
            i++;
    }
    System.out.println(s);

This code works fine with most inputs I tested including the example mentioned above, except when the input x is 70 then the output is 11 and 30, instead of 11 and 40.

What I'm trying to understand basically is when should I decrease j and when should I increment i so that the code works on every possible x input.

The solution must be O(n) time complexity.

Appreciate the help! (If you find mistakes in my English, please let me know, I'm trying to improve.)

Upvotes: 2

Views: 717

Answers (3)

user16320675
user16320675

Reputation: 135

Basically similar to question's code (a bit simpler?):

// returning an array so I can check against brute force algorithm
private static int[] closestPair(int[] a, int[] b, int x) {
    int closest = Integer.MAX_VALUE;
    int[] result = { -1, -1 };    // could use null
    int i = 0;
    int j = b.length-1;
    while (i < a.length && j >= 0) {
        int diff= (a[i] + b[j]) - x;

        // is it closer?
        if (abs(diff) < closest) {
            closest = abs(diff);
            result[0] = a[i];
            result[1] = b[j];
        }

        // which pointer to change for next iteration
        if (diff == 0) break;  // shortcut, can't get closer
        if (diff < 0) {
            i++;               // sum was less than x, try higher value
        } else {
            j--;               // sum was greater, try a smaller one
        }
    }
    return result;
}

Upvotes: 0

Oleg Cherednik
Oleg Cherednik

Reputation: 18255

public static int[] getClosestPairSum(int[] A, int[] B, int x) {
    TreeSet<Integer> unique = new TreeSet<>();

    for (int a : A)
        unique.add(a);

    int absDiff = -1;
    int[] res = { 0, 0 };

    for (int b : B) {
        for (Integer aa : Arrays.asList(unique.floor(x - b), unique.ceiling(x - b))) {
            if (aa == null)
                continue;

            int curAbsDiff = Math.abs(x - b - aa);

            if (absDiff == -1 || curAbsDiff < absDiff) {
                absDiff = curAbsDiff;
                res[0] = aa;
                res[1] = b;
            }
        }
    }

    return res;
}

Upvotes: 0

Code Plus
Code Plus

Reputation: 170

You should use Two Pointer method to get desired result. Below code will work for you.

       while (i <= a.length-1 && j >= 0) {
    
            if (Math.abs((b[j]+a[i]) - x ) < closest || Math.abs( (b[j]+a[i]) - x) == 0) {
                closest = Math.abs(x - (b[j]+a[i])) ;
                s = a[i] + " " +  "and" + " " + b[j];
            }
            
            if (b[j]+a[i] > x) j --;
            else i++;
        }

Time complexity is definitely O(n).

For detailed instructions please visit here on GeeksforGeeks.

Upvotes: 2

Related Questions