📌  相关文章
📜  前缀和和后缀和数组的可能数组计数

📅  最后修改于: 2021-04-25 00:12:55             🧑  作者: Mango

给定2 * N个整数,它们是大小为N的数组的前缀和后缀数组(按乱序排列)的元素,任务是查找大小为N的可能数组的数目,这些数组可以由这些元素构成

例子:

方法:

  • 可以得出的一个见解是,如果给定数组的所有元素之和除以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))