Tuesday, May 2, 2017

Find subset of two or three numbers in a sorted array that sum upto a given value

Problem Statement

Given a number and a sorted array print all possible subsets containing two numbers that sum unto the given number.

Example 1:  array: [-3, -2, -1, 0, 1, 2,  3, 4,  5, 6, 7],  sum: 0
The 2-subsets are [-3, 3], [-2, 2] and [-1 , 1]

Example 2:  array: [1, 3, 4, 5, 6, 7],  sum: 6
The 2-subsets is [1, 5]

This is an instance of well known subset sum problem. But it's not as hard as we just need to produce subsets of 2 numbers. The idea here is to maintain two pointers, one starting from the left (lb) and the other starting from the right (ub). If the sum of x[lb] and x[ub] equals to the sum, we have identified the first subset. If it  is smaller than the sum, then move lb to the right otherwise move ub to the left. Keep on doing this until lb meets ub.

This problem is pretty straightforward and a working solution is given below:

void sum2(int x[], int n, int sum) {

    int lb = 0;
    int ub = n - 1;

    while(lb < ub) {

        if (x[lb] + x[ub] > sum) {
            ub--;
        } else if(x[lb] + x[ub] < sum) {
            lb++;
        } else  {
            std::cout << x[lb] << ", " << x[ub] << std::endl;
            lb++;
            ub--;
        }
    }
}
This solution can easily be extended to 3-subset. All we need is to find subset of two elements for each element in the array. The solution is given below:
void sum3(int x[], int n, int sum) {

    int lb = 0;
    int ub = n - 1;

    for (int i = 0; i < n; i++) {

        int lb = i + 1;
        int ub = n - 1;
        int num = sum - x[i];

        while(lb < ub) {

            if (x[lb] + x[ub] > num) {
                ub--;
            } else if(x[lb] + x[ub] < num) {
                lb++;
            } else  {
                std::cout << x[i] << ", " << x[lb] << ", " << x[ub] << std::endl;
                lb++;
                ub--;
            }
        }
    }
}

No comments:

Post a Comment