给定一个由N 个整数组成的数组arr[] ,任务是计算在将单个数组元素更改为0后将数组拆分为两个相等和的子数组的方法的数量。
例子:
Input: arr[] = {1, 2, -1, 3}
Output: 4
Explanation:
Replacing arr[0] by 0, arr[] is modified to {0, 2, -1, 3}. Only 1 possible split is {0, 2} and {-1, 3}.
Replacing arr[1] by 0, arr[] is modified to {1, 0, -1, 3}. No way to split the array.
Replacing arr[2] by 0, arr[] is modified to {1, 2, 0, 3}. The 2 possible splits are {1, 2, 0} and {3}, {1, 2} and {0, 3}.
Replacing arr[3] by 0, arr[] is modified to {1, 2, -1, 0}. Only 1 possible split is {1} and {2, -1, 0}.
Therefore, the total number of ways to split = 1 + 0 + 2 + 1 = 4.
Input: arr[] = {1, 2, 1, 1, 3, 1}
Output: 6
Explanation:
Replacing arr[0] by 0, arr[] is modified to {0, 2, 1, 1, 3, 1}. Only 1 possible split exists.
Replacing arr[1] by 0, arr[] is modified to {1, 0, 1, 1, 3, 1}. No way to split the array.
Replacing arr[2] by 0, arr[] is modified to {1, 2, 0, 1, 3, 1}. Only 1 possible split exists.
Replacing arr[3] by 0, arr[] is modified to {1, 2, 1, 0, 3, 1}. Only 2 possible splits exist.
Replacing arr[4] by 0, arr[] is modified to {1, 2, 1, 1, 0, 1}. Only 1 possible split exists.
Replacing arr[5] by 0, arr[] is modified to {1, 2, 1, 1, 3, 0}. Only 1 possible split exists.
Total number of ways to split is = 1 + 0 + 1 + 2 + 1 + 1 = 6.
朴素的方法:解决问题的最简单的方法是遍历数组,将每个数组元素arr[i]转换为0,并计算将修改后的数组拆分为两个和相等的子数组的方法的数量。
时间复杂度: O(N 2 )
辅助空间: O(1)
高效的方法:为了优化上述方法,该想法基于以下观察:
Considering two arrays arr1[] and arr2[] with sum of the array elements equal to sum_arr1 and sum_arr2 respectively.
Let dif be the difference between sum_arr1 and sum_arr2, i.e., sum_arr1 – sum_arr2 = dif.
Now, sum_arr1 can be made equal to sum_arr2 by performing any one of the two operations:
- Remove an element from arr1[] whose value is equal to dif.
- Remove an element from arr2[] whose value is equal to -dif.
Therefore, the total number of ways to obtain sum_arr1 = sum_arr2 is equal to the count of dif in arr1 + count of (-dif) in arr2.
对于[0, N – 1]范围内的每个索引,可以通过将当前索引视为分裂点,通过使用上述过程使任何元素等于0来获得路径总数。请按照以下步骤解决问题:
- 初始化变量计数与0来存储所希望的结果,并用0 prefix_sum的到前缀总和和suffixSum存储与0来存储后缀总和。
- 初始化哈希映射prefixCount和suffixCount以存储前缀和后缀数组中的元素计数。
- 遍历arr[]并更新suffixCount中每个元素的频率。
- 使用变量i在[0, N – 1]范围内遍历 arr[] 。
- 将arr[i]添加到prefixCount哈希映射并将其从suffixCount 中删除。
- 到prefixSum和组suffixSum添加ARR [I]到阵列的总和的差 和prefixSum 。
- 将子数组的总和之间的差值存储在变量dif = prefix_sum – suffixSum 中。
- 在number_of_subarray_at_i_split 中存储第i个索引处的拆分方式数,并且等于prefixCount和suffixCount的总和。
- 通过向其添加number_of_subarray_at_i_split来更新计数。
- 完成以上步骤后,打印count的值作为结果。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find number of ways to
// split array into 2 subarrays having
// equal sum by changing element to 0 once
int countSubArrayRemove(int arr[], int N)
{
// Stores the count of elements
// in prefix and suffix of
// array elements
unordered_map
prefix_element_count,
suffix_element_count;
// Stores the sum of array
int total_sum_of_elements = 0;
// Traverse the array
for (int i = N - 1; i >= 0; i--) {
total_sum_of_elements += arr[i];
// Increase the frequency of
// current element in suffix
suffix_element_count[arr[i]]++;
}
// Stores prefix sum upto index i
int prefix_sum = 0;
// Stores sum of suffix of index i
int suffix_sum = 0;
// Stores the desired result
int count_subarray_equal_sum = 0;
// Traverse the array
for (int i = 0; i < N; i++) {
// Modify prefix sum
prefix_sum += arr[i];
// Add arr[i] to prefix map
prefix_element_count[arr[i]]++;
// Calculate suffix sum by
// subtracting prefix sum
// from total sum of elements
suffix_sum = total_sum_of_elements
- prefix_sum;
// Remove arr[i] from suffix map
suffix_element_count[arr[i]]--;
// Store the difference
// between the subarrays
int difference = prefix_sum
- suffix_sum;
// Count number of ways to split
// the array at index i such that
// subarray sums are equal
int number_of_subarray_at_i_split
= prefix_element_count[difference]
+ suffix_element_count[-difference];
// Update the final result
count_subarray_equal_sum
+= number_of_subarray_at_i_split;
}
// Return the result
return count_subarray_equal_sum;
}
// Driver Code
int main()
{
int arr[] = { 1, 2, 1, 1, 3, 1 };
int N = sizeof(arr) / sizeof(arr[0]);
// Function Call
cout << countSubArrayRemove(arr, N);
return 0;
}
Java
// Java program for the above approach
import java.util.*;
class GFG{
// Function to find number of ways to
// split array into 2 subarrays having
// equal sum by changing element to 0 once
static int countSubArrayRemove(int []arr, int N)
{
// Stores the count of elements
// in prefix and suffix of
// array elements
HashMap prefix_element_count = new HashMap();
HashMap suffix_element_count = new HashMap();
// Stores the sum of array
int total_sum_of_elements = 0;
// Traverse the array
for(int i = N - 1; i >= 0; i--)
{
total_sum_of_elements += arr[i];
// Increase the frequency of
// current element in suffix
if (!suffix_element_count.containsKey(arr[i]))
suffix_element_count.put(arr[i], 1);
else
suffix_element_count.put(arr[i],
suffix_element_count.get(arr[i]) + 1);
}
// Stores prefix sum upto index i
int prefix_sum = 0;
// Stores sum of suffix of index i
int suffix_sum = 0;
// Stores the desired result
int count_subarray_equal_sum = 0;
// Traverse the array
for(int i = 0; i < N; i++)
{
// Modify prefix sum
prefix_sum += arr[i];
// Add arr[i] to prefix map
if (!prefix_element_count.containsKey(arr[i]))
prefix_element_count.put(arr[i], 1);
else
prefix_element_count.put(arr[i],
prefix_element_count.get(arr[i]) + 1);
// Calculate suffix sum by
// subtracting prefix sum
// from total sum of elements
suffix_sum = total_sum_of_elements -
prefix_sum;
// Remove arr[i] from suffix map
if (!suffix_element_count.containsKey(arr[i]))
suffix_element_count.put(arr[i], 0);
else
suffix_element_count.put(arr[i],
suffix_element_count.get(arr[i]) - 1);
// Store the difference
// between the subarrays
int difference = prefix_sum -
suffix_sum;
// Count number of ways to split
// the array at index i such that
// subarray sums are equal
int number_of_subarray_at_i_split = 0;
if (prefix_element_count.containsKey(difference))
number_of_subarray_at_i_split =
prefix_element_count.get(difference);
if (suffix_element_count.containsKey(-difference))
number_of_subarray_at_i_split +=
suffix_element_count.get(-difference);
// Update the final result
count_subarray_equal_sum +=
number_of_subarray_at_i_split;
}
// Return the result
return count_subarray_equal_sum;
}
// Driver Code
public static void main(String args[])
{
int []arr = { 1, 2, 1, 1, 3, 1 };
int N = arr.length;
// Function Call
System.out.println(countSubArrayRemove(arr, N));
}
}
// This code is contributed by Stream_Cipher
Python3
# Python3 program for the above approach
# Function to find number of ways to
# split array into 2 subarrays having
# equal sum by changing element to 0 once
def countSubArrayRemove(arr, N):
# Stores the count of elements
# in prefix and suffix of
# array elements
prefix_element_count = {}
suffix_element_count = {}
# Stores the sum of array
total_sum_of_elements = 0
# Traverse the array
i = N - 1
while (i >= 0):
total_sum_of_elements += arr[i]
# Increase the frequency of
# current element in suffix
suffix_element_count[arr[i]] = suffix_element_count.get(
arr[i], 0) + 1
i -= 1
# Stores prefix sum upto index i
prefix_sum = 0
# Stores sum of suffix of index i
suffix_sum = 0
# Stores the desired result
count_subarray_equal_sum = 0
# Traverse the array
for i in range(N):
# Modify prefix sum
prefix_sum += arr[i]
# Add arr[i] to prefix map
prefix_element_count[arr[i]] = prefix_element_count.get(
arr[i], 0) + 1
# Calculate suffix sum by
# subtracting prefix sum
# from total sum of elements
suffix_sum = total_sum_of_elements - prefix_sum
# Remove arr[i] from suffix map
suffix_element_count[arr[i]] = suffix_element_count.get(
arr[i], 0) - 1
# Store the difference
# between the subarrays
difference = prefix_sum - suffix_sum
# Count number of ways to split
# the array at index i such that
# subarray sums are equal
number_of_subarray_at_i_split = (prefix_element_count.get(
difference, 0) +
suffix_element_count.get(
-difference, 0))
# Update the final result
count_subarray_equal_sum += number_of_subarray_at_i_split
# Return the result
return count_subarray_equal_sum
# Driver Code
if __name__ == '__main__':
arr = [ 1, 2, 1, 1, 3, 1 ]
N = len(arr)
# Function Call
print(countSubArrayRemove(arr, N))
# This code is contributed by SURENDRA_GANGWAR
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG{
// Function to find number of ways to
// split array into 2 subarrays having
// equal sum by changing element to 0 once
static int countSubArrayRemove(int []arr, int N)
{
// Stores the count of elements
// in prefix and suffix of
// array elements
Dictionary prefix_element_count = new Dictionary ();
Dictionarysuffix_element_count = new Dictionary ();
// Stores the sum of array
int total_sum_of_elements = 0;
// Traverse the array
for(int i = N - 1; i >= 0; i--)
{
total_sum_of_elements += arr[i];
// Increase the frequency of
// current element in suffix
if (!suffix_element_count.ContainsKey(arr[i]))
suffix_element_count[arr[i]] = 1;
else
suffix_element_count[arr[i]]++;
}
// Stores prefix sum upto index i
int prefix_sum = 0;
// Stores sum of suffix of index i
int suffix_sum = 0;
// Stores the desired result
int count_subarray_equal_sum = 0;
// Traverse the array
for(int i = 0; i < N; i++)
{
// Modify prefix sum
prefix_sum += arr[i];
// Add arr[i] to prefix map
if (!prefix_element_count.ContainsKey(arr[i]))
prefix_element_count[arr[i]] = 1;
else
prefix_element_count[arr[i]]++;
// Calculate suffix sum by
// subtracting prefix sum
// from total sum of elements
suffix_sum = total_sum_of_elements -
prefix_sum;
// Remove arr[i] from suffix map
if (!suffix_element_count.ContainsKey(arr[i]))
suffix_element_count[arr[i]] = 0;
else
suffix_element_count[arr[i]]-= 1;
// Store the difference
// between the subarrays
int difference = prefix_sum -
suffix_sum;
// Count number of ways to split
// the array at index i such that
// subarray sums are equal
int number_of_subarray_at_i_split = 0;
if (prefix_element_count.ContainsKey(difference))
number_of_subarray_at_i_split
= prefix_element_count[difference];
if (suffix_element_count.ContainsKey(-difference))
number_of_subarray_at_i_split
+= suffix_element_count[-difference];
// Update the final result
count_subarray_equal_sum
+= number_of_subarray_at_i_split;
}
// Return the result
return count_subarray_equal_sum;
}
// Driver Code
public static void Main(string []args)
{
int []arr = { 1, 2, 1, 1, 3, 1 };
int N = arr.Length;
// Function Call
Console.Write(countSubArrayRemove(arr, N));
}
}
// This code is contributed by chitranayal
6
时间复杂度: O(N)
辅助空间: O(N)
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live