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.
- Sort the array in ascending order.
- 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.
- Consider the element with value 4. Since there are 5 elements with value 4, they can pair amongst themselves in ways[4] ways.
- The left out element will have to pair with an element with value 3. This happens in 4 ways since there are 4 elements with value 3.
- One element of value 3 will be reserved to pair with an element of 4, so 3 elements with value 3 remain.
- Two of the remaining elements with value 3 will pair amongst themselves in ways[2] ways.
- One element of value 3 will be left, which will pair with the element with value 2 in 1 way.
- The lone element will be selected from the remaining 3 elements in 3 ways.
- Therefore, the total number of ways to pair the elements in the given sorted array is the product of the ways calculated in steps 1-6.
- Therefore from point 1, number of ways will be :
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define S second
#define ll long long
using namespace std;
const int mod = 1000000007;
const int MAX = 100000;
ll ways[MAX + 1];
void preCompute()
{
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< 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));
}
sort(count_vector.begin(), count_vector.end());
ll ans = 1;
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;
if (current_count & 1) {
ans = (ans * ways[current_count - 1]) % mod;
ans = (ans * current_count) % mod;
ans = (ans * prev_count) % mod;
if (prev_count & 1) {
ans = (ans * ways[prev_count - 1]) % mod;
count_vector[i - 1].S = 0;
}
else {
count_vector[i - 1].S--;
}
}
else {
ans = (ans * ways[current_count]) % mod;
}
}
ans = (ans * ways[count_vector[0].S]) % mod;
cout << ans << "\n" ;
}
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;
}
|
Java
import java.util.*;
class GFG
{
static int mod = 1000000007 ;
static int MAX = 100000 ;
static long [] ways = new long [MAX + 1 ];
static void preCompute()
{
ways[ 0 ] = 1 ;
ways[ 2 ] = 1 ;
for ( int i = 4 ; i <= MAX; i += 2 ) {
ways[i] = ((i - 1 ) * ways[i - 2 ]) % mod;
}
}
static void countWays( int [] arr, int n)
{
TreeMap<Integer, Integer> count = new TreeMap<Integer, Integer>();
for ( int i = 0 ; i < n; i++)
{
if (!count.containsKey(arr[i]))
count.put(arr[i], 0 );
count.put(arr[i], count.get(arr[i]) + 1 );
}
ArrayList<ArrayList<Integer>> count_vector = new ArrayList<ArrayList<Integer>>();
for (Map.Entry<Integer, Integer> entry : count.entrySet())
{
ArrayList<Integer> l = new ArrayList<Integer>();
l.add(entry.getKey());
l.add(entry.getValue());
count_vector.add(l);
}
Collections.sort(count_vector, new Comparator<ArrayList<Integer>> () {
@Override
public int compare(ArrayList<Integer> a, ArrayList<Integer> b) {
if (a.get( 0 ) == b.get( 0 ))
return a.get( 1 ).compareTo(b.get( 1 ));
return a.get( 0 ).compareTo(b.get( 0 ));
}
});
long ans = 1 ;
for ( int i = count_vector.size() - 1 ; i > 0 ; i--) {
int current_count = count_vector.get(i).get( 1 );
int prev_count = count_vector.get(i - 1 ).get( 1 );
if ((current_count & 1 ) != 0 ) {
ans = (ans * ways[current_count - 1 ]) % mod;
ans = (ans * current_count) % mod;
ans = (ans * prev_count) % mod;
if ((prev_count & 1 ) != 0 ) {
ans = (ans * ways[prev_count - 1 ]) % mod;
count_vector.get(i - 1 ).set( 1 , 0 );
}
else {
count_vector.get(i - 1 ).set( 1 , count_vector.get(i - 1 ).get( 1 ) - 1 ); ;
}
}
else {
ans = (ans * ways[current_count]) % mod;
}
}
ans = (ans * ways[count_vector.get( 0 ).get( 1 )]) % mod;
System.out.println(ans);
}
public static void main(String[] args)
{
preCompute();
int [] arr = { 2 , 3 , 3 , 3 , 3 , 4 , 4 , 4 , 4 , 4 };
int n = arr.length;
countWays(arr, n);
}
}
|
Python3
from collections import defaultdict
mod = 1000000007
MAX = 100000
ways = [ None ] * ( MAX + 1 )
def preCompute():
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):
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]])
count_vector.sort()
ans = 1
for i in range ( len (count_vector) - 1 , - 1 , - 1 ):
current_count = count_vector[i][ 1 ]
prev_count = count_vector[i - 1 ][ 1 ]
if current_count & 1 :
ans = (ans * ways[current_count - 1 ]) % mod
ans = (ans * current_count) % mod
ans = (ans * prev_count) % mod
if prev_count & 1 :
ans = (ans * ways[prev_count - 1 ]) % mod
count_vector[i - 1 ][ 1 ] = 0
else :
count_vector[i - 1 ][ 1 ] - = 1
else :
ans = (ans * ways[current_count]) % mod
ans = (ans * ways[count_vector[ 0 ][ 1 ]]) % mod
print (ans)
if __name__ = = "__main__" :
preCompute()
arr = [ 2 , 3 , 3 , 3 , 3 , 4 , 4 , 4 , 4 , 4 ]
n = len (arr)
countWays(arr, n)
|
C#
using System;
using System.Linq;
using System.Collections.Generic;
class GFG
{
static int mod = 1000000007;
static int MAX = 100000;
static long [] ways = new long [MAX + 1];
static void preCompute()
{
ways[0] = 1;
ways[2] = 1;
for ( int i = 4; i <= MAX; i += 2) {
ways[i] = ((i - 1) * ways[i - 2]) % mod;
}
}
static void countWays( int [] arr, int n)
{
Dictionary< int , int > count = new Dictionary< int , int >();
for ( int i = 0; i < n; i++)
{
if (!count.ContainsKey(arr[i]))
count[arr[i]] = 0;
count[arr[i]]++;
}
List< int []> count_vector = new List< int []>();
List< int > keys = new List< int >(count.Keys);
keys.Sort();
foreach ( var key in keys)
count_vector.Add( new int []{key, count[key]});
count_vector = count_vector.OrderBy(r => r[0])
.ThenBy(r => r[1])
.ToList();
long ans = 1;
for ( int i = count_vector.Count - 1; i > 0; i--) {
int current_count = count_vector[i][1];
int prev_count = count_vector[i - 1][1];
if ((current_count & 1) != 0) {
ans = (ans * ways[current_count - 1]) % mod;
ans = (ans * current_count) % mod;
ans = (ans * prev_count) % mod;
if ((prev_count & 1) != 0) {
ans = (ans * ways[prev_count - 1]) % mod;
count_vector[i - 1][1] = 0;
}
else {
count_vector[i - 1][1]--;
}
}
else {
ans = (ans * ways[current_count]) % mod;
}
}
ans = (ans * ways[count_vector[0][1]]) % mod;
Console.WriteLine(ans);
}
public static void Main( string [] args)
{
preCompute();
int [] arr = { 2, 3, 3, 3, 3, 4, 4, 4, 4, 4 };
int n = arr.Length;
countWays(arr, n);
}
}
|
Javascript
let mod = 1000000007
let MAX = 100000
let ways = new Array(MAX + 1)
function preCompute()
{
ways[0] = 1
ways[2] = 1
for ( var i = 4; i < MAX + 1; i += 2)
ways[i] = ((1 * (i - 1) * ways[i - 2]) % mod)
}
function countWays(arr, n)
{
let count = {}
for ( var i = 0; i < n; i++)
{
if (!count.hasOwnProperty(arr[i]))
count[arr[i]] = 0;
count[arr[i]] += 1
}
let count_vector = []
for ( var [key, value] of Object.entries(count))
count_vector.push([key, value])
count_vector.sort()
let ans = 1
for ( var i = (count_vector).length - 1; i > 0; i--)
{
let current_count = count_vector[i][1]
let prev_count = count_vector[i - 1][1]
if (current_count & 1)
{
ans = (ans * ways[current_count - 1]) % mod
ans = (ans * current_count) % mod
ans = (ans * prev_count) % mod
if (prev_count & 1)
{
ans = (ans * ways[prev_count - 1]) % mod
count_vector[i - 1][1] = 0
}
else
{
count_vector[i - 1][1] -= 1
}
}
else
{
ans = (ans * ways[current_count]) % mod
}
}
ans = (ans * ways[count_vector[0][1]]) % mod
console.log(ans)
}
preCompute()
let arr = [2, 3, 3, 3, 3, 4, 4, 4, 4, 4]
let n = arr.length
countWays(arr, n)
|
Time Complexity:
The preCompute function has a time complexity of O(MAX), where MAX is the maximum value of the input array. The countWays function has a time complexity of O(n log n), where n is the size of the input array, due to the sorting operation. Therefore, the overall time complexity of the program is O(MAX + n log n).
Auxiliary Space:
The program uses an array called ways of size MAX + 1, so the auxiliary space complexity is O(MAX). Additionally, the program uses a map and a vector to store the count of elements and their frequencies, respectively. The space required for the map and vector is proportional to the number of distinct elements in the input array, which is at most MAX. Therefore, the overall auxiliary space complexity is O(MAX).
Space Complexity:
The space complexity of the program is the sum of the time complexity and the auxiliary space complexity. Therefore, the space complexity of the program is O(MAX + n log n).
Last Updated :
28 Jan, 2024
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...