📌  相关文章
📜  通过改变任何一个数组元素的符号来计算将数组分成两个相等和子数组的方法

📅  最后修改于: 2021-09-06 11:27:08             🧑  作者: Mango

给定一个由N 个整数组成的数组arr[] ,任务是通过改变任何一个数组元素的符号来计算将数组分成两个相等和的子数组的方法。

例子:

朴素的方法:解决问题的最简单的方法是遍历数组并逐个改变每个数组元素的符号,并计算每次更改将数组拆分为两个相等和子数组的方法的数量。最后,打印所有可能方式的总和。
时间复杂度: O(N 2 )
辅助空间: O(1)

高效方法:为了优化上述方法,其思想是存储每个数组索引的前缀和和后缀和,以在O(1)计算复杂度中找到拆分器子数组的总和。请按照以下步骤解决问题:

  • 初始化一个变量,比如count ,以存储拆分数组的方法数。
  • 0初始化两个变量,比如prefixSumsuffixSum ,以存储两个数组的前缀和后缀和。
  • 初始化两个 Map prefixCountsuffixCount以存储前缀和后缀数组中的元素计数。
  • 遍历数组arr[]并更新suffixCount中每个元素的频率。
  • 遍历数组arr[]并执行以下步骤:
    • arr[i]插入prefixCount映射并将其从suffixCount 中删除。
    • prefixSum和组suffixSum添加ARR [I]到阵列和prefixSum的总和之差。
    • 将子数组总和之间的差值,即prefixSum – suffixSum 存储在一个变量中,比如diff
    • 在第i索引处拆分的方式数计算如下:
      • 如果diff为奇数,则无法拆分数组。
      • 如果diff是偶数,则将值(prefixCount + suffixCount[ -diff / 2]) 添加count
  • 完成上述步骤后, count的值给出了可能的拆分总数。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to count ways of splitting
// the array in two subarrays of equal
// sum by changing sign of any 1 element
int countSubArraySignChange(int arr[], int N)
{
    // Stores the count of elements
    // in prefix and suffix of array
    unordered_map prefixCount;
    unordered_map suffixCount;
 
    // Stores the total sum of array
    int total = 0;
 
    // Traverse the array
    for (int i = N - 1; i >= 0; i--) {
 
        total += arr[i];
 
        // Increase the frequency of
        // current element in suffix
        suffixCount[arr[i]]++;
    }
 
    // Stores prefix sum upto
    // an index
    int prefixSum = 0;
 
    // Stores sum of suffix
    // from an index
    int suffixSum = 0;
 
    // Stores the count of ways to
    // split the array in 2 subarrays
    // having equal sum
    int count = 0;
 
    // Traverse the array
    for (int i = 0; i < N - 1; i++) {
 
        // Modify prefix sum
        prefixSum += arr[i];
 
        // Add arr[i] to prefix Map
        prefixCount[arr[i]]++;
 
        // Calculate suffix sum by
        // subtracting prefix sum
        // from total sum of elements
        suffixSum = total - prefixSum;
 
        // Remove arr[i] from suffix Map
        suffixCount[arr[i]]--;
 
        // Store the difference
        // between the subarrays
        int diff = prefixSum - suffixSum;
 
        // Check if diff is even or not
        if (diff % 2 == 0) {
 
            // Count number of ways to
            // split array at index i such
            // that subarray sums are same
            int x = prefixCount
                    + suffixCount[-diff / 2];
 
            // Update the count
            count = count + x;
        }
    }
 
    // Return the count
    return count;
}
 
// Driver Code
int main()
{
    int arr[] = { 2, 2, -3, 3 };
    int N = sizeof(arr) / sizeof(arr[0]);
 
    // Function Call
    cout << countSubArraySignChange(arr, N);
 
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
class GFG{
 
// Function to count ways of splitting
// the array in two subarrays of equal
// sum by changing sign of any 1 element
static int countSubArraySignChange(int arr[], int N)
{
   
    // Stores the count of elements
    // in prefix and suffix of array
    HashMap prefixCount = new HashMap();
    HashMap suffixCount = new HashMap();
 
    // Stores the total sum of array
    int total = 0;
 
    // Traverse the array
    for (int i = N - 1; i >= 0; i--)
    {
 
        total += arr[i];
 
        // Increase the frequency of
        // current element in suffix
        if(suffixCount.containsKey(arr[i])){
            suffixCount.put(arr[i], suffixCount.get(arr[i]) + 1);
        }
        else{
            suffixCount.put(arr[i], 1);
        }
    }
 
    // Stores prefix sum upto
    // an index
    int prefixSum = 0;
 
    // Stores sum of suffix
    // from an index
    int suffixSum = 0;
 
    // Stores the count of ways to
    // split the array in 2 subarrays
    // having equal sum
    int count = 0;
 
    // Traverse the array
    for (int i = 0; i < N - 1; i++)
    {
 
        // Modify prefix sum
        prefixSum += arr[i];
 
        // Add arr[i] to prefix Map
        if(prefixCount.containsKey(arr[i]))
        {
            prefixCount.put(arr[i], prefixCount.get(arr[i])+1);
        }
        else
        {
            prefixCount.put(arr[i], 1);
        }
 
        // Calculate suffix sum by
        // subtracting prefix sum
        // from total sum of elements
        suffixSum = total - prefixSum;
 
        // Remove arr[i] from suffix Map
        if(suffixCount.containsKey(arr[i]))
        {
            suffixCount.put(arr[i], suffixCount.get(arr[i]) - 1);
        }
 
        // Store the difference
        // between the subarrays
        int diff = prefixSum - suffixSum;
 
        // Check if diff is even or not
        if (diff % 2 == 0)
        {
 
            // Count number of ways to
            // split array at index i such
            // that subarray sums are same
            int x = (prefixCount.containsKey(diff / 2)?prefixCount.get(diff / 2):0)
                    + (suffixCount.containsKey(-diff / 2)?suffixCount.get(-diff / 2):0);
 
            // Update the count
            count = count + x;
        }
    }
 
    // Return the count
    return count;
}
 
// Driver Code
public static void main(String[] args)
{
    int arr[] = { 2, 2, -3, 3 };
    int N = arr.length;
 
    // Function Call
    System.out.print(countSubArraySignChange(arr, N));
}
}
 
// This code is contributed by 29AjayKumar


Python3
# Python3 program for the above approach
 
# Function to count ways of spliting
# the array in two subarrays of equal
# sum by changing sign of any 1 element
def countSubArraySignChange(arr, N):
     
    # Stores the count of elements
    # in prefix and suffix of array
    prefixCount = {}
    suffixCount = {}
 
    # Stores the total sum of array
    total = 0
 
    # Traverse the array
    for i in range(N - 1, -1, -1):
 
        total += arr[i]
 
        # Increase the frequency of
        # current element in suffix
        suffixCount[arr[i]] = suffixCount.get(arr[i], 0) + 1
 
    # Stores prefix sum upto
    # an index
    prefixSum = 0
 
    # Stores sum of suffix
    # from an index
    suffixSum = 0
 
    # Stores the count of ways to
    # split the array in 2 subarrays
    # having equal sum
    count = 0
 
    # Traverse the array
    for i in range(N - 1):
 
        # Modify prefix sum
        prefixSum += arr[i]
 
        # Add arr[i] to prefix Map
        prefixCount[arr[i]] = prefixCount.get(arr[i], 0) + 1
 
        # Calculate suffix sum by
        # subtracting prefix sum
        # from total sum of elements
        suffixSum = total - prefixSum
 
        # Remove arr[i] from suffix Map
        suffixCount[arr[i]] -= 1
 
        # Store the difference
        # between the subarrays
        diff = prefixSum - suffixSum
 
        # Check if diff is even or not
        if (diff % 2 == 0):
 
            # Count number of ways to
            # split array at index i such
            # that subarray sums are same
            y, z = 0, 0
            if -diff//2 in suffixCount:
                y = suffixCount[-dff//2]
            if diff//2 in prefixCount:
                z = prefixCount
            x = z+ y
 
            # Update the count
            count = count + x
 
    # Return the count
    return count
 
# Driver Code
if __name__ == '__main__':
    arr=[2, 2, -3, 3]
    N = len(arr)
 
    # Function Call
    print(countSubArraySignChange(arr, N))
 
    # This code is contributed by mohit kumar 29


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
  // Function to count ways of splitting
  // the array in two subarrays of equal
  // sum by changing sign of any 1 element
  static int countSubArraySignChange(int []arr, int N)
  {
 
    // Stores the count of elements
    // in prefix and suffix of array
    Dictionary prefixCount = new Dictionary();
    Dictionary suffixCount = new Dictionary();
 
    // Stores the total sum of array
    int total = 0;
 
    // Traverse the array
    for (int i = N - 1; i >= 0; i--)
    {
 
      total += arr[i];
 
      // Increase the frequency of
      // current element in suffix
      if(suffixCount.ContainsKey(arr[i])){
        suffixCount[arr[i]] = suffixCount[arr[i]] + 1;
      }
      else{
        suffixCount.Add(arr[i], 1);
      }
    }
 
    // Stores prefix sum upto
    // an index
    int prefixSum = 0;
 
    // Stores sum of suffix
    // from an index
    int suffixSum = 0;
 
    // Stores the count of ways to
    // split the array in 2 subarrays
    // having equal sum
    int count = 0;
 
    // Traverse the array
    for (int i = 0; i < N - 1; i++)
    {
 
      // Modify prefix sum
      prefixSum += arr[i];
 
      // Add arr[i] to prefix Map
      if(prefixCount.ContainsKey(arr[i]))
      {
        prefixCount[arr[i]] = prefixCount[arr[i]] + 1;
      }
      else
      {
        prefixCount.Add(arr[i], 1);
      }
 
      // Calculate suffix sum by
      // subtracting prefix sum
      // from total sum of elements
      suffixSum = total - prefixSum;
 
      // Remove arr[i] from suffix Map
      if(suffixCount.ContainsKey(arr[i]))
      {
        suffixCount[arr[i]] = suffixCount[arr[i]] - 1;
      }
 
      // Store the difference
      // between the subarrays
      int diff = prefixSum - suffixSum;
 
      // Check if diff is even or not
      if (diff % 2 == 0)
      {
 
        // Count number of ways to
        // split array at index i such
        // that subarray sums are same
        int x = (prefixCount.ContainsKey(diff / 2)?prefixCount:0)
          + (suffixCount.ContainsKey(-diff / 2)?suffixCount[-diff / 2]:0);
 
        // Update the count
        count = count + x;
      }
    }
 
    // Return the count
    return count;
  }
 
  // Driver Code
  public static void Main(String[] args)
  {
    int []arr = { 2, 2, -3, 3 };
    int N = arr.Length;
 
    // Function Call
    Console.Write(countSubArraySignChange(arr, N));
  }
}
 
 
// This code is contributed by 29AjayKumar


输出:
2

时间复杂度: O(N)
辅助空间: O(N)

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live