Open In App

Count of possible arrays from prefix-sum and suffix-sum arrays

Given 2*N integers which are elements of a prefix and suffix array(in shuffled order) of an array of size N, the task is to find the no of possible array’s of the size N which can be made from these elements 
Examples: 
 

Input: arr[] = {5, 2, 3, 5} 
Output:
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 
 

 

Approach: 
 

Below is the implementation of the above approach.
 




// C++ implementation of the above approach
#include <bits/stdc++.h>
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<int, int> 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 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<Integer,Integer> mp = new HashMap<Integer,Integer>();        
 
    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<Integer,Integer> 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 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




using System;
using System.Collections.Generic;
 
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 *= a;
            }
            a *= a;
            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 *= i;
        }
        return fact;
    }
 
    // Function to print the number of arrays
    static void FindNoOfArrays(int[] a, int n)
    {
        int sum = 0, s1, c = 0;
        Dictionary<int, int> mp
            = new Dictionary<int, int>();
 
        // Calculating the sum of elements and initializing
        // the frequency in the dictionary
        for (int i = 0; i < 2 * n; i++) {
            if (!mp.ContainsKey(a[i])) {
                mp[a[i]] = 1;
            }
            else {
                mp[a[i]]++;
            }
            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.ContainsKey(s1) && mp[s1] >= 2) {
            mp[s1] -= 2;
        }
        else {
            isArrayPossible = false;
        }
 
        // Check if the array is possible based on frequency
        // of elements
        if (isArrayPossible) {
            var keys = new List<int>(mp.Keys);
            foreach(var key in keys)
            {
                if (mp.ContainsKey(s1 - key)) {
                    if (key == s1 - key) {
                        if (mp[key] % 2 != 0) {
                            isArrayPossible = false;
                            break;
                        }
                    }
                    else {
                        if (mp[key] != mp[s1 - key]) {
                            isArrayPossible = false;
                            break;
                        }
                    }
                    if (mp[key] > 0) {
                        if (key != s1 - key) {
                            c += mp[key];
                            ans *= Power(2, mp[key]);
                            ans /= Factorial(mp[key]);
                            mp[key] = 0;
                            mp[s1 - key] = 0;
                        }
                        if (key == s1 - key) {
                            c += mp[key] / 2;
                            ans /= Factorial(mp[key] / 2);
                            mp[key] = 0;
                        }
                    }
                }
            }
        }
 
        // Check if it is possible to make the array and if
        // there are n-1 pairs whose sum will be equal to s1
        if (c < n - 1 && !isArrayPossible) {
            Console.WriteLine("0");
        }
        else {
            Console.WriteLine(ans);
        }
    }
 
    // Main method
    public static void Main(string[] args)
    {
        // First input array and function call
        int[] arr1 = { 5, 2, 3, 5 };
        int n1 = arr1.Length;
        FindNoOfArrays(arr1, n1 / 2);
 
        // Second input array and function call
        int[] arr2
            = { -1, -1, -1, 0, 1, 0, 1, 0, 1, 0, 0, 0 };
        int n2 = arr2.Length;
        FindNoOfArrays(arr2, n2 / 2);
    }
}




// JavaScript implementation of the above approach
 
// Function to find power of
// a number.
function power(a, b)
{
    let result = 1;
    while (b > 0) {
        if (b % 2 == 1) {
            result = result * a;
        }
        a = a * a;
        b = Math.floor(b / 2);
    }
    return result;
}
 
// Function to find
// factorial of a number.
function factorial(n)
{
    let fact = 1;
    for (let i = 1; i <= n; i++) {
        fact = fact * i;
    }
    return fact;
}
 
// Function to print no of arrays
function findNoOfArrays(a, n)
{
    // c variable counts the no of pairs
    let sum = 0, s1, c = 0;
 
    // Map to store the frequency
    // of each element
    let mp = {};
     
    let keys = []
    for (var i = 0; i < 2 * n; i++)
    {
        var ele = a[i]
        if (!mp.hasOwnProperty(ele))
        {
            mp[ele] = 1
            keys.push(ele)
        }
        else
        {
            mp[ele] += 1
        }
         
             
     
        // Sum of all elements of the array
        sum += ele;
    }
 
    // Variable to check if it is
    // possible to make any array
    let isArrayPossible = true;
    let ans = factorial(n - 1);
 
    // First element of suffix array
    // and the last element of prefix array
    s1 = Math.floor(sum / (n + 1));
     
    if (!mp.hasOwnProperty(s1))
        mp[s1] = 0;
         
    // Check if the element exists in the map
    if (mp[s1] >= 2) {
        mp[s1] = mp[s1] - 2;
    }
    else {
        isArrayPossible = false;
    }
     
 
    if (isArrayPossible) {
        for (var first of keys) {
            var second = mp[first]
             
            // 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
            first = parseInt(first);
            second = parseInt(second);
 
                 
            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 (mp.hasOwnProperty(s1 - first))
                {
                    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 = Math.floor(ans / factorial(second));
 
                    // Make frequency of both these elements 0
 
                    mp[first] = 0;
                    mp[s1 - first] = 0;
                }
                else {
                    // Update the count of pairs
 
                    c = c + Math.floor(second / 2);
 
                    // Divide the answer by the factorial
                    // of no. of similar pairs
 
                    ans = Math.floor(ans / factorial(Math.floor(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 || isArrayPossible == false) {
        console.log(0);
    }
    else {
        console.log(ans);
    }
     
}
 
// Driver code
let arr1 = [ 5, 2, 3, 5 ];
let n1 = arr1.length;
 
// Function calling
findNoOfArrays(arr1, Math.floor(n1 / 2));
 
let arr2 =[ -1, -1, -1, 0, 1, 0,
                1, 0, 1, 0, 0, 0 ];
let n2 = arr2.length;
findNoOfArrays(arr2, Math.floor(n2 / 2));
 
// This code is contributed by phasing17

Output
2
80

Time complexity: O(N Log(N))

Auxiliary Space: O(N)
 


Article Tags :