给定N个整数的数组arr ,任务是将数组的元素拆分为N / 2对(每对具有2个元素),以使任何一对中的两个元素之间的绝对差值尽可能小。
注意: N将始终为偶数。
例子:
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
方法:此问题涉及计数的基本原理以及对排列和组合的一些基本理解。
在继续之前,让我们计算一下数组的方法数量= [3,3]
答案= 1,因为只能有1种组合。
现在,让我们将数组修改为[3,3,3,3]。以上示例中讨论的方法是:
(1, 2), (3, 4)
(1, 3), (2, 4)
(1, 4), (2, 3)
Answer = 3 ways.
进一步将数组修改为[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.
在这里,我们通过简单的观察获得广义的结果。如果数组中有K个元素具有相同的值,而K为偶数,则在它们之间形成对的方式的数目为:
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)
我们可以如下计算该结果。令Ways []为数组,使ways [i]存储大小为’i’的Ways数量。
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].
现在,计数不必总是保持偶数。因此,如果需要为通用数组解决此问题,我们需要做两件事。
- 以升序对数组进行排序。
- 分析具有相同值的每个组的计数。
让我们的数组= [2,3,3,3,3,4,4,4,4,4,4] 。该数组已排序。
- 考虑具有值4的元素。由于有5个元素,所以4个元素将以ways [4]的方式相互配对。剩下的元素可以通过5种方式选择。剩余的元素将必须与值3的元素配对。由于存在4个具有值3的元素,因此以4种方式发生。因此,将保留值3的一个元素与4的元素进行配对。因此3个元素与值3保留下来。 2将以Ways [2]的方式彼此配对,而1将以1的方式与值为2的元素配对。同样,将通过3种方式选择lone元素。
- 因此,从第1点开始,方法的数量将是:
ways[4] * 5 * 4 * ways[2] * 3 * 1 = 180
下面是上述方法的实现:
C++
// C++ implementation of the above approach
#include
#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 count;
for (int i = 0; i < n; i++)
count[arr[i]]++;
vector > count_vector;
map::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
180