2

I am given two arrays (can contain duplicates and of same length) containing positive integers. I have to find the maximum number of pairs that have absolute difference less than equal to a particular value (given) when numbers can be used only once from both the arrays.

For example:

arr1 = {1,2,3,4}
arr2 = {8,9,10,11}
diff = 5

Then, possible pairs are (3,8), (4,8). That is, only two such possible pairs are there.

Output should be 2.

Also, I can think of an algo for this in O(n^2). But, I need something better. I thought of hash maps (won't work because arrays contain duplicates), thought of sorting the arrays in descending and ascending order, wasn't really able to move forward from there.

John Lui
  • 1,434
  • 3
  • 23
  • 37
  • Your 2nd sentence is not clearly written. Do you mean: "I have to find the number of unique pairs that have absolute difference less than or equal to a given value." – Karlis Olte Jun 20 '15 at 20:43
  • Yes, but the if the numbers are used once to form a pair, they cant be used again. – John Lui Jun 20 '15 at 20:46
  • I'm voting to close this question as off-topic because this is an on-going competition which will be finished in a day. – Salvador Dali Jun 20 '15 at 21:29

1 Answers1

0

The usual idea is to loop over sorted ranges. This, you can bring down the brute-force O(N^2) effort to usually O(N log N).

Here is an algorithm for that in pseudo code (maybe I'll update later with real C++ code):

  • Sort both arrays
  • Loop over both simultaneously with two iterators:
    1. If a pair is found insert it into your list. Increase both iterators.
    2. Otherwise, increase the indicator pointing to the smaller element.

In total, this is dominated by the sort which on average takes O(N log N).


Here is the promised code:

auto find_pairs(std::vector<int>& arr1, std::vector<int>& arr2, int diff)
{
    std::vector<std::pair<int,int> > ret;

    std::sort(std::begin(arr1), std::end(arr1));
    std::sort(std::begin(arr2), std::end(arr2));

    auto it1= std::begin(arr1);
    auto it2= std::begin(arr2);

    while(it1!= std::end(arr1) && it2!= std::end(arr2))
    {
        if(std::abs(*it1-*it2) == diff)
        {
            ret.push_back(std::make_pair(*it1,*it2));
            ++it1;
            ++it2;
        }
        else if(*it1<*it2)
        {
            ++it1;
        }
        else
        {
            ++it2;
        }
    }

    return ret;
}

It returns the matching elements of the two vectors as a vector of std::pairs. For your example, it prints

3  8
4  9

DEMO

davidhigh
  • 14,652
  • 2
  • 44
  • 75
  • Great algorithm. Simple to understand. Works perfectly. Thanks – John Lui Jun 20 '15 at 20:46
  • Actually I think this doesn't work. Check for `arr1 = [1 2 3 4]` `arr2 = [1 2 3 4]` `diff=5` from what I understand it should give 16 pairs. – Saeid Jun 20 '15 at 21:00
  • @sudomakeinstall2 Your counter argument is not very clear, can you please elaborate. – Steephen Jun 20 '15 at 21:02
  • @sudomakeinstall2: I think your example should give 0 pairs. No two elements have a difference of 5. – davidhigh Jun 20 '15 at 21:08
  • Check the provided code for the arrays mentioned above. It returns 0 pairs. But From what I understand every pair has the mentioned condition so it should return 16 pairs. – Saeid Jun 20 '15 at 21:09
  • the question explicitly says `absolute difference less than equal to a particular value ` not `equal` – Saeid Jun 20 '15 at 21:10
  • Sorry, I didn't understand the question completely. Your algorithm is fine. – Saeid Jun 20 '15 at 21:13
  • @sudomakeinstall2: correct. So then one should replace the `==` by a `<=` (or better: use a general predicate). Still, your issue can only be answered by the OP: shall it be *with or without duplicates*. – davidhigh Jun 20 '15 at 21:14