Skip to content
Related Articles

Related Articles

Ways to form n/2 pairs such that difference of pairs is minimum

View Discussion
Improve Article
Save Article
  • Difficulty Level : Easy
  • Last Updated : 11 Jul, 2022

Given an array arr of N integers, the task is to split the elements of the array into N/2 pairs (each pair having 2 elements) such that the absolute difference between two elements of any pair is as minimum as possible. Note: N will always be even. Examples:

Input: arr[] = {1, 7, 3, 8} Output: 1 There is only one way to form pairs with minimum difference, (7, 8) and (1, 3). Input: arr[] = {1, 1, 1, 1, 2, 2, 2, 2} Output: 9 Here all elements with value 2 will pair amongst themselves (3 ways possible) and all elements with value 1 will make pairs between them (3 ways possible) Therefore, number of ways = 3 * 3 = 9 Input: arr[] = {2, 3, 2, 2} Output: 3

Approach: This problem involves the fundamental principle of counting and some basic understanding of permutations and combinations. Before going any further, let’s count the number of ways for the array = [3, 3] Answer = 1, since only 1 combination is possible. Now, lets modify the array to [3, 3, 3, 3]. The ways for this as discussed in the above examples are:

(1, 2), (3, 4) (1, 3), (2, 4) (1, 4), (2, 3) Answer = 3 ways.

Further modifying the array to [3, 3, 3, 3, 3, 3]

(1, 2), (3, 4), (5, 6) (1, 2), (3, 5), (4, 6) (1, 2), (3, 6), (4, 5) (1, 3), (2, 4), (5, 6) (1, 3), (2, 5), (4, 6) (1, 3), (2, 6), (4, 5) (1, 4), (2, 3), (5, 6) (1, 4), (2, 5), (3, 6) (1, 4), (2, 6), (3, 5) (1, 5), (2, 3), (4, 6) (1, 5), (2, 4), (3, 6) (1, 5), (2, 6), (3, 4) (1, 6), (2, 3), (4, 5) (1, 6), (2, 4), (3, 5) (1, 6), (2, 5), (3, 4) Answer = 15 ways.

Here we obtain a generalized result by simple observation. If there are K elements in the array that have the same value and K is even, then the number of ways to form pairs amongst them:

For size 2, count = 1 (1) For size 4, count = 3 (1 * 3) For size 6, count = 15 (1 * 3 * 5) And so on. Hence, number of ways to form pairs for size K where K is even = 1 * 3 * 5 * …. * (K-1)

We can precompute this result as follows. Let ways[] be the array such that ways[i] stores the number of ways for size ‘i’.

ways[2] = 1; for(i = 4; i < 1e5 + 1; i += 2) ways[i] = ways[i – 2] * (i – 1); For example, we consider array [3, 3, 3, 3, 3] To compute the number of ways, we fix the first element with any of the remaining 5. So we form one pair. Now 4 elements are left that can be paired in ways[4] ways. So number of ways would be 5 * ways[4].

Now, it may not be necessary that counts may always be even in number. Therefore, if need to solve this for a general array, we need to do two things.

  1. Sort the array in ascending order.
  2. Analyze the count of each group having the same value.

Let our array = [2, 3, 3, 3, 3, 4, 4, 4, 4, 4]. This array is sorted.

  • Considering element with value 4. Since there are 5 elements, 4 elements will pair amongst themselves in ways[4] ways. The left out element can be chosen in 5 ways. The element left will have to pair with an element with value 3. This happens in 4 ways since there are 4 elements with value 3. Therefore, one element of value 3 will be reserved to pair with an element of 4. So 3 elements with value 3 remain. 2 will pair amongst themselves in ways[2] ways and one 1 will pair with the element with value 2 in 1 way. Again, the lone element will be selected in 3 ways.
  • Therefore from point 1, number of ways will be :

Below is the implementation of the above approach: 

C++




// C++ implementation of the above approach
#include <bits/stdc++.h>
 
#define mp make_pair
#define pb push_back
#define S second
#define ll long long
 
using namespace std;
 
// Using mod because the number
// of ways might be very large
const int mod = 1000000007;
 
const int MAX = 100000;
 
// ways is serving the same
// purpose as discussed
ll ways[MAX + 1];
 
void preCompute()
{
    // pairing up zero people
    // requires one way.
    ways[0] = 1LL;
    ways[2] = 1LL;
    for (int i = 4; i <= MAX; i += 2) {
        ways[i] = (1LL * (i - 1) * ways[i - 2]) % mod;
    }
}
 
void countWays(int* arr, int n)
{
 
    // map count stores count of s.
    map<int, int> count;
    for (int i = 0; i < n; i++)
        count[arr[i]]++;
 
    vector<pair<int, int> > count_vector;
    map<int, int>::iterator it;
    for (it = count.begin(); it != count.end(); it++) {
        count_vector.pb(mp(it->first, it->second));
    }
 
    // vector count_vector stores a
    // pair < value, count of value>
 
    // sort according to value
    sort(count_vector.begin(), count_vector.end());
 
    ll ans = 1;
 
    // Iterating backwards.
    for (int i = count_vector.size() - 1; i > 0; i--) {
 
        int current_count = count_vector[i].S;
        int prev_count = count_vector[i - 1].S;
 
        // Checking if current count is odd.
        if (current_count & 1) {
 
            // if current count = 5, multiply ans by ways[4].
            ans = (ans * ways[current_count - 1]) % mod;
 
            // left out person will be selected
            // in current_count ways
            ans = (ans * current_count) % mod;
 
            // left out person will pair with previous
            //  person in previous_count ways
            ans = (ans * prev_count) % mod;
 
            /* if previous count is odd,
             * then multiply answer by ways[prev_count-1].
             * since one has already been reserved,
             * remaining will be even.
             * reduce prev_count = 0, since we don't need it now.*/
            if (prev_count & 1) {
                ans = (ans * ways[prev_count - 1]) % mod;
                count_vector[i - 1].S = 0;
            }
            else {
 
                /* if prev count is even, one will be reserved,
                 * therefore decrement by 1.
                 * In the next iteration, prev_count will become odd
                 * and it will be handled in the same way.*/
                count_vector[i - 1].S--;
            }
        }
        else {
 
            /* if current count is even,
             * then simply multiply ways[current_count]
             * to answer.*/
            ans = (ans * ways[current_count]) % mod;
        }
    }
 
    /* multiply answer by ways[first__count] since
       that is left out, after iterating the array.*/
    ans = (ans * ways[count_vector[0].S]) % mod;
    cout << ans << "\n";
}
 
// Driver code
int main()
{
    preCompute();
    int arr[] = { 2, 3, 3, 3, 3, 4, 4, 4, 4, 4 };
    int n = sizeof(arr) / sizeof(arr[0]);
    countWays(arr, n);
    return 0;
}

Python3




# Python3 implementation of the
# above approach
from collections import defaultdict
 
# Using mod because the number
# of ways might be very large
mod = 1000000007
MAX = 100000
 
# ways is serving the same
# purpose as discussed
ways = [None] * (MAX + 1)
 
def preCompute():
 
    # pairing up zero people
    # requires one way.
    ways[0] = 1
    ways[2] = 1
    for i in range(4, MAX + 1, 2):
        ways[i] = ((1 * (i - 1) *
                    ways[i - 2]) % mod)
 
def countWays(arr, n):
 
    # map count stores count of s.
    count = defaultdict(lambda:0)
    for i in range(0, n):
        count[arr[i]] += 1
 
    count_vector = []
    for key in count:
        count_vector.append([key, count[key]])
 
    # vector count_vector stores a
    # pair < value, count of value>
 
    # sort according to value
    count_vector.sort()
    ans = 1
 
    # Iterating backwards.
    for i in range(len(count_vector) - 1, -1, -1):
 
        current_count = count_vector[i][1]
        prev_count = count_vector[i - 1][1]
 
        # Checking if current count is odd.
        if current_count & 1:
 
            # if current count = 5, multiply
            # ans by ways[4].
            ans = (ans * ways[current_count - 1]) % mod
 
            # left out person will be selected
            # in current_count ways
            ans = (ans * current_count) % mod
 
            # left out person will pair with previous
            # person in previous_count ways
            ans = (ans * prev_count) % mod
 
            # if previous count is odd,
            # then multiply answer by ways[prev_count-1].
            # since one has already been reserved,
            # remaining will be even.
            # reduce prev_count = 0, since we
            # don't need it now.
            if prev_count & 1:
                ans = (ans * ways[prev_count - 1]) % mod
                count_vector[i - 1][1] = 0
             
            else:
 
                # if prev count is even, one will be
                # reserved, therefore decrement by 1.
                # In the next iteration, prev_count
                # will become odd and it will be
                # handled in the same way.
                count_vector[i - 1][1] -= 1
             
        else:
 
            # if current count is even, then simply
            # multiply ways[current_count] to answer.
            ans = (ans * ways[current_count]) % mod
         
    # multiply answer by ways[first__count] since
    # that is left out, after iterating the array.
    ans = (ans * ways[count_vector[0][1]]) % mod
    print(ans)
 
# Driver code
if __name__ == "__main__":
 
    preCompute()
    arr = [2, 3, 3, 3, 3, 4, 4, 4, 4, 4]
    n = len(arr)
    countWays(arr, n)
     
# This code is contributed by Rituraj Jain

Output:

180

Time Complexity: O(nlogn)

Auxiliary Space: O(MAX + n)


My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!