给定2 * N个整数,它们是大小为N的数组的前缀和后缀数组(按乱序排列)的元素,任务是查找大小为N的可能数组的数目,这些数组可以由这些元素构成
例子:
Input: arr[] = {5, 2, 3, 5}
Output: 2
Explanation:
1st array can be : {2, 3}
Its prefix array:{2, 5}
Its suffix array:{5, 3}
2nd array can be : {3, 2}
Its prefix array : {3, 5}
Its suffix array : {5, 2}
Input: arr[] = {-1, -1, -1, 0, 1, 0, 1, 0, 1, 0, 0, 0}
Output: 80
方法:
- 可以得出的一个见解是,如果给定数组的所有元素之和除以n + 1,则分别获得前缀和后缀数组的最后一个元素和第一个元素。
- 通过观察前缀和后缀数组的元素可以得出此结论。前缀数组的第一元素和后缀数组的第二元素之和等于前缀数组的第二元素和后缀数组的第三元素之和(如果后缀数组中有第三个元素),以此类推。
在图像中,第一个数组是给定的数组,第二个是前缀数组,第三个是后缀数组。- 这些对的总和等于要找到的数组中所有元素的总和。
- 如果假定对的总和为s1,并且所有前缀和后缀元素的总和为s,则:
s1 *(n-1)+ 2 * s1 = s
s1 = s /(n + 1)
其中s1是前缀数组的最后一个元素和后缀数组的第一个元素。 - 现在,需要找到总和等于s1的所有其他对,这可以使用哈希映射来完成。
- 如果将这些对与数组一起线性拖曳,则可以得到答案为
(n-1)! /(k1!* k2!…kr!)
其中k1,k2…kr是相似对的数量 - 每对也可以在前缀和后缀数组中互换(如果对的元素不相等),因此答案变为
(n-1)! *(2 ^ p)/(k1!* k2!…kr!)
其中p是总和等于s1的数组中不重复对的数目。
下面是上述方法的实现。
C++
// C++ implementation of the above approach
#include
using namespace std;
// Function to find power of
// a number.
int power(int a, int b)
{
int result = 1;
while (b > 0) {
if (b % 2 == 1) {
result = result * a;
}
a = a * a;
b = b / 2;
}
return result;
}
// Function to find
// factorial of a number.
int factorial(int n)
{
int fact = 1;
for (int i = 1; i <= n; i++) {
fact = fact * i;
}
return fact;
}
// Function to print no of arrays
void findNoOfArrays(int* a, int n)
{
// c variable counts the no of pairs
int sum = 0, s1, c = 0;
// Map to store the frequency
// of each element
map mp;
for (int i = 0; i < 2 * n; i++) {
mp[a[i]]++;
// Sum of all elements of the array
sum = sum + a[i];
}
// Variable to check if it is
// possible to make any array
bool isArrayPossible = true;
int ans = factorial(n - 1);
// First element of suffix array
// and the last element of prefix array
s1 = sum / (n + 1);
// Check if the element exists in the map
if (mp[s1] >= 2) {
mp[s1] = mp[s1] - 2;
}
else {
isArrayPossible = false;
}
if (isArrayPossible) {
for (auto i : mp) {
// If elements of any pair are equal
// and their frequency is not divisible by 2
// update the isArrayPossible variable
// to false and break through the loop
if (i.first == s1 - i.first) {
if (mp[i.first] % 2 != 0) {
isArrayPossible = false;
break;
}
}
// If elements of any pair are not equal
// and their frequency is not same
// update the isArrayPossible variable
// to false and break through the loop
if (i.first != s1 - i.first) {
if (mp[i.first]
!= mp[s1 - i.first]) {
isArrayPossible = false;
break;
}
}
// Check if frequency is greater than zero
if (i.second > 0) {
if (i.first != s1 - i.first) {
// update the count of pairs
c = c + i.second;
// Multiply the answer by
// 2^(frequency of pairs) since
// the elements of the pair are
// not the same in this condition
ans = ans * power(2, i.second);
// Divide the answer by the factorial
// of no of similar pairs
ans = ans / factorial(i.second);
// Make frequency of both these elements 0
mp[i.first] = 0;
mp[s1 - i.first] = 0;
}
if (i.first == s1 - i.first) {
// Update the count of pairs
c = c + i.second / 2;
// Divide the answer by the factorial
// of no. of similar pairs
ans = ans / factorial(i.second / 2);
// Make frequency of this element 0
mp[i.first] = 0;
}
}
}
}
// Check if it is possible to make the
// array and there are n-1 pairs
// whose sum will be equal to s1
if (c < n - 1 || isArrayPossible == false) {
cout << "0" << endl;
}
else {
cout << ans << endl;
}
}
// Driver code
int main()
{
int arr1[] = { 5, 2, 3, 5 };
int n1 = sizeof(arr1) / sizeof(arr1[0]);
// Function calling
findNoOfArrays(arr1, n1 / 2);
int arr2[] = { -1, -1, -1, 0, 1, 0,
1, 0, 1, 0, 0, 0 };
int n2 = sizeof(arr2) / sizeof(arr2[0]);
findNoOfArrays(arr2, n2 / 2);
return 0;
}
Java
// Java implementation of the above approach
import java.util.*;
class GFG{
// Function to find power of
// a number.
static int power(int a, int b)
{
int result = 1;
while (b > 0) {
if (b % 2 == 1) {
result = result * a;
}
a = a * a;
b = b / 2;
}
return result;
}
// Function to find
// factorial of a number.
static int factorial(int n)
{
int fact = 1;
for (int i = 1; i <= n; i++) {
fact = fact * i;
}
return fact;
}
// Function to print no of arrays
static void findNoOfArrays(int[] a, int n)
{
// c variable counts the no of pairs
int sum = 0, s1, c = 0;
// Map to store the frequency
// of each element
HashMap mp = new HashMap();
for (int i = 0; i < 2 * n; i++) {
if(mp.get(a[i])==null)
mp.put(a[i], 1);
else
mp.put(a[i], mp.get(a[i]) + 1);
// Sum of all elements of the array
sum = sum + a[i];
}
// Variable to check if it is
// possible to make any array
boolean isArrayPossible = true;
int ans = factorial(n - 1);
// First element of suffix array
// and the last element of prefix array
s1 = sum / (n + 1);
// Check if the element exists in the map
if (mp.get(s1) >= 2) {
mp.replace(s1, mp.get(s1) - 2);
}
else {
isArrayPossible = false;
}
if (isArrayPossible) {
for (Map.Entry m:mp.entrySet()) {
// If elements of any pair are equal
// and their frequency is not divisible by 2
// update the isArrayPossible variable
// to false and break through the loop
if (m.getKey() == s1-m.getKey()) {
if (mp.get(m.getKey()) % 2 != 0) {
isArrayPossible = false;
break;
}
}
// If elements of any pair are not equal
// and their frequency is not same
// update the isArrayPossible variable
// to false and break through the loop
if (m.getKey() != s1 - m.getKey()) {
if (mp.get(m.getKey())
!= mp.get(s1 - m.getKey())) {
isArrayPossible = false;
break;
}
}
// Check if frequency is greater than zero
if (m.getValue() > 0) {
if (m.getKey() != s1 - m.getKey()) {
// update the count of pairs
c = c + m.getValue();
// Multiply the answer by
// 2^(frequency of pairs) since
// the elements of the pair are
// not the same in this condition
ans = ans * power(2, m.getValue());
// Divide the answer by the factorial
// of no of similar pairs
ans = ans / factorial(m.getValue());
// Make frequency of both these elements 0
mp.replace(m.getKey(),0);
mp.replace(s1 - m.getKey(),0);
}
if (m.getKey() == s1 - m.getKey()) {
// Update the count of pairs
c = c + m.getValue() / 2;
// Divide the answer by the factorial
// of no. of similar pairs
ans = ans / factorial(m.getValue() / 2);
// Make frequency of this element 0
mp.replace(m.getKey(),0);
}
}
}
}
// Check if it is possible to make the
// array and there are n-1 pairs
// whose sum will be equal to s1
if (c < n - 1 && isArrayPossible == false) {
System.out.println("0");
}
else {
System.out.println(ans);
}
}
// Driver code
public static void main(String args[])
{
int[] arr1 = { 5, 2, 3, 5 };
int n1 = arr1.length;
// Function calling
findNoOfArrays(arr1, n1 / 2);
int []arr2 = { -1, -1, -1, 0, 1, 0,
1, 0, 1, 0, 0, 0 };
int n2 = arr2.length;
findNoOfArrays(arr2, n2 / 2);
}
}
// This code is contributed by Surendra_Gangwar
Python3
# Python3 implementation of the above approach
# Function to find power of
# a number.
def power(a, b) :
result = 1;
while (b > 0) :
if (b % 2 == 1) :
result = result * a;
a = a * a;
b = b // 2;
return result;
# Function to find
# factorial of a number.
def factorial(n) :
fact = 1;
for i in range(1, n + 1) :
fact = fact * i;
return fact;
# Function to print no of arrays
def findNoOfArrays(a, n) :
# c variable counts the no of pairs
sum = 0; c = 0;
# Map to store the frequency
# of each element
mp = dict.fromkeys(a, 0);
for i in range(2 * n) :
mp[a[i]] += 1;
# Sum of all elements of the array
sum = sum + a[i];
# Variable to check if it is
# possible to make any array
isArrayPossible = True;
ans = factorial(n - 1);
# First element of suffix array
# and the last element of prefix array
s1 = sum // (n + 1);
# Check if the element exists in the map
if (mp[s1] >= 2) :
mp[s1] = mp[s1] - 2;
else :
isArrayPossible = False;
if (isArrayPossible) :
for first,second in mp.items() :
# If elements of any pair are equal
# and their frequency is not divisible by 2
# update the isArrayPossible variable
# to false and break through the loop
if (first == s1 - first) :
if (mp[first] % 2 != 0) :
isArrayPossible = False;
break;
# If elements of any pair are not equal
# and their frequency is not same
# update the isArrayPossible variable
# to false and break through the loop
if (first != s1 - first) :
if s1 - first in mp :
if (mp[first] != mp[s1 - first]) :
isArrayPossible = False;
break;
# Check if frequency is greater than zero
if (second > 0) :
if (first != s1 - first) :
# update the count of pairs
c = c + second;
# Multiply the answer by
# 2^(frequency of pairs) since
# the elements of the pair are
# not the same in this condition
ans = ans * power(2, second);
# Divide the answer by the factorial
# of no of similar pairs
ans = ans / factorial(second);
# Make frequency of both these elements 0
mp[first] = 0;
mp[s1 - first] = 0;
if (first == s1 - first) :
# Update the count of pairs
c = c + second // 2;
# Divide the answer by the factorial
# of no. of similar pairs
ans = ans // factorial(second // 2);
# Make frequency of this element 0
mp[first] = 0;
# Check if it is possible to make the
# array and there are n-1 pairs
# whose sum will be equal to s1
if (c < n - 1 or isArrayPossible == False) :
print("0");
else:
print(ans);
# Driver code
if __name__ == "__main__" :
arr1 = [ 5, 2, 3, 5 ];
n1 = len(arr1);
# Function calling
findNoOfArrays(arr1, n1 // 2);
arr2 = [ -1, -1, -1, 0, 1, 0,
1, 0, 1, 0, 0, 0 ];
n2 = len(arr2);
findNoOfArrays(arr2, n2 // 2);
# This code is contributed by AnkitRai01
输出:
2
80
时间复杂度: O(N Log(N))