给定一个由N 个整数组成的数组arr[] ,任务是通过改变任何一个数组元素的符号来计算将数组分成两个相等和的子数组的方法。
例子:
Input: arr[] = {2, 2, -3, 3}
Output: 2
Explanation:
Changing arr[0] = 2 to arr[0] = -2, the array becomes {-2, 2, -3, 3}. Only 1 possible split is {-2, 2} and {-3, 3}.
Changing arr[1] = 2 to arr[1] = -2, the array becomes {2, -2, -3, 3}. Only 1 possible split is {-2, 2} and {-3, 3}.
Changing arr[2] = -3 to arr[2] = 3, the array becomes {2, 2, 3, 3}. No way to split the array.
Changing arr[3] = 3 to arr[2] = -3, the array becomes {2, 2, -3, -3}. No way to split the array.
Therefore, the total number of ways to split = 1 + 1 + 0 + 0 = 2.
Input: arr[] = {2, 2, 1, -3, 3}
Output: 0
朴素的方法:解决问题的最简单的方法是遍历数组并逐个改变每个数组元素的符号,并计算每次更改将数组拆分为两个相等和子数组的方法的数量。最后,打印所有可能方式的总和。
时间复杂度: O(N 2 )
辅助空间: O(1)
高效方法:为了优化上述方法,其思想是存储每个数组索引的前缀和和后缀和,以在O(1)计算复杂度中找到拆分器子数组的总和。请按照以下步骤解决问题:
- 初始化一个变量,比如count ,以存储拆分数组的方法数。
- 用0初始化两个变量,比如prefixSum和suffixSum ,以存储两个数组的前缀和后缀和。
- 初始化两个 Map prefixCount和suffixCount以存储前缀和后缀数组中的元素计数。
- 遍历数组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
Javascript
2
时间复杂度: O(N)
辅助空间: O(N)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。