📌  相关文章
📜  计算将数组分成三个连续部分的方法数,总和相等

📅  最后修改于: 2022-05-13 01:57:50.745000             🧑  作者: Mango

计算将数组分成三个连续部分的方法数,总和相等

给定一个包含 n 个数字的数组。我们的任务是找出将数组分成三个连续部分以使三个部分之和相等的方法的数量。换句话说,我们需要找到索引对 i 和 j 的数量,使得从 0 到 i-1 的元素之和等于从 i 到 j 的元素之和等于从 j+1 到的元素之和n-1。

例子:

Input  : arr[] = {1, 2, 3, 0, 3}
Output : 2
Following are two possible ways to partition
1) Three parts are (1, 2), (3) and (0, 3)
2) Three parts are (1, 2), (3,0) and (3)

Input : arr[] = {0, 1, -1, 0}
Output : 1
It is only one way to partition.
1) Three parts are (0), (1,-1) and (0)

如果数组中所有元素的总和不能被 3 整除,则返回 0。否则,很明显,每个连续部分的每个部分的总和将等于所有元素的总和除以 3。

步骤 1:创建一个与给定数组大小相同的数组,其第 i 个索引保存给定数组从索引 0 到 i 的元素之和的值。我们称之为前缀数组
步骤 2:创建另一个与给定数组大小相同的数组,其第 i 个索引是给定数组的从索引 i 到 n-1 的元素总和的值。我们称它为后缀数组。
第三步:思路很简单,我们开始遍历前缀数组,假设在前缀数组的第 i 个索引处,前缀数组的值等于(给定数组的所有元素之和)/3。
第 4 步:对于我在上述步骤中找到的 i,我们从第 (i+2) 个索引查看后缀数组,并且无论后缀数组的值等于(给定数组的所有元素的总和)/3,我们增加计数器变量加 1。

为了实现第 4 步,我们遍历 suffix 数组,只要 suffix 数组的值等于给定数组的所有元素的总和/3,我们就将 suffix 数组的索引推入向量中。我们在向量中进行二分搜索,以计算后缀数组中的值的数量,如步骤 4 所示。

我们在后缀数组中搜索,因为第一部分和第三部分之间应该至少有一个元素。

有关更多说明,请参见下面的实现

C++
// C++ program to count number of ways we can
// partition an array in three parts with equal
// sum.
#include
using namespace std;
 
// binary search to find the number of required
// indices in suffix array. Returns index of
// first element which is greater than x.
int binarysearch(vector  &v, int x)
{
    int low = 0, high = v.size()-1;
    while (low <= high)
    {
        int mid = (low + high)/2;
        if (v[mid] <= x)
            low = mid + 1;
        else if (v[mid] > x && v[mid-1] <= x)
            return mid;
        else if (v[mid] > x && mid == 0)
            return mid;
        else
            high = mid-1;
    }
    return -1;
}
 
// function to calculate the number of ways to
// divide the array into three contiguous parts
int CountContiguousParts(int arr[] ,int n)
{
    int count = 0;  // initializing answer
 
    // Creating and filling  prefix array
    int prefix[n];
    prefix[0] = arr[0];
    for (int i=1; i=0; i--)
        suffix[i] = suffix[i+1] + arr[i];
 
    // Storing all indexes with suffix
    // sum equal to total sum by 3.
    vector  v;
    for (int i=0; i


Java
// Java program to count number of ways we can
// partition an array in three parts with equal
// sum.
import java.util.*;
 
class GFG
{
 
// binary search to find the number of required
// indices in suffix array. Returns index of
// first element which is greater than x.
static int binarysearch(Vector v, int x)
{
    int low = 0, high = v.size() - 1;
    while (low <= high)
    {
        int mid = (low + high) / 2;
        if (v.get(mid) <= x)
            low = mid + 1;
        else if (v.get(mid) > x &&
                 v.get(mid) <= x)
            return mid;
        else if (v.get(mid) > x && mid == 0)
            return mid;
        else
            high = mid - 1;
    }
    return -1;
}
 
// function to calculate the number of ways to
// divide the array into three contiguous parts
static int CountContiguousParts(int arr[], int n)
{
    int count = 0; // initializing answer
 
    // Creating and filling prefix array
    int []prefix = new int[n];
    prefix[0] = arr[0];
    for (int i = 1; i < n; i++)
        prefix[i] = prefix[i - 1] + arr[i];
 
    // Total sum of elements is equal to last
    // value in prefix array.
    int total_sum = prefix[n - 1];
 
    // If sum of all the elements is not divisible
    // by 3, we can't divide array in 3 parts of
    // same sum.
    if (total_sum % 3 != 0)
        return 0;
 
    // Creating and filling suffix array
    int []suffix = new int[n];
    suffix[n - 1] = arr[n - 1];
    for (int i = n - 2; i >= 0; i--)
        suffix[i] = suffix[i + 1] + arr[i];
 
    // Storing all indexes with suffix
    // sum equal to total sum by 3.
    Vector v = new Vector<>();
    for (int i = 0; i < n; i++)
        if (suffix[i] == total_sum / 3)
            v.add(i);
 
    // Traversing the prefix array and
    // doing binary search in above vector
    for (int i = 0; i < n; i++)
    {
        // We found a prefix with total_sum/3
        if (prefix[i] == total_sum / 3)
        {
            // Find first index in v[] which
            // is greater than i+1.
            int res = binarysearch(v, i + 1);
 
            if (res != -1)
                count += v.size() - res;
        }
    }
    return count;
}
 
// Driver Code
public static void main(String[] args)
{
    int arr[] = {1 , 2 , 3 , 0 , 3};
    int n = arr.length;
    System.out.println(CountContiguousParts(arr, n));
}
}
 
// This code is contributed by Princi Singh


Python3
# Python 3 program to count the number of ways we can
# partition an array in three parts with equal
# sum.
 
# binary search to find the number of required
# indices in suffix array. Returns index of
# first element which is greater than x.
def binarysearch(v, x):
    low = 0
    high = len(v) - 1
    while (low <= high):
        mid = int((low + high) / 2)
        if (v[mid] <= x):
            low = mid + 1
        elif (v[mid] > x and v[mid - 1] <= x):
            return mid
        elif (v[mid] > x and mid == 0):
            return mid
        else:
            high = mid - 1
 
    return -1
 
# function to calculate the number of ways to
# divide the array into three contiguous parts
def CountContiguousParts(arr,n):
    count = 0 # initializing answer
 
    # Creating and filling prefix array
    prefix = [0 for i in range(n)]
    prefix[0] = arr[0]
    for i in range(1, n, 1):
        prefix[i] = prefix[i - 1] + arr[i]
 
    # Total sum of elements is equal to last
    # value in prefix array.
    total_sum = prefix[n - 1]
 
    # If sum of all the elements is not divisible
    # by 3, we can't divide array in 3 parts of
    # same sum.
    if (total_sum % 3 != 0):
        return 0
 
    # Creating and filling suffix array
    suffix = [0 for i in range(n)]
    suffix[n - 1] = arr[n - 1]
    i = n - 2
    while(i >= 0):
        suffix[i] = suffix[i + 1] + arr[i]
        i -= 1
 
    # Storing all indexes with suffix
    # sum equal to total sum by 3.
    v = []
    for i in range(n):
        if (suffix[i] == int(total_sum / 3)):
            v.append(i)
 
    # Traversing the prefix array and
    # doing binary search in above vector
    for i in range(n):
         
        # We found a prefix with total_sum/3
        if (prefix[i] == int(total_sum / 3)):
             
            # Find first index in v[] which
            # is greater than i+1.
            res = binarysearch(v, i + 1)
 
            if (res != -1):
                count += len(v) - res
 
    return count
 
# Driver Code
if __name__ == '__main__':
    arr = [1 , 2 , 3 , 0 , 3]
    n = len(arr)
    print(CountContiguousParts(arr, n))
 
# This code is contributed by
# Surendra_Gangwar


C#
// C# program to count number of ways we can
// partition an array in three parts with equal
using System;
using System.Collections.Generic;
 
class GFG
{
 
// binary search to find the number of required
// indices in suffix array. Returns index of
// first element which is greater than x.
static int binarysearch(List v, int x)
{
    int low = 0, high = v.Count - 1;
    while (low <= high)
    {
        int mid = (low + high) / 2;
        if (v[mid] <= x)
            low = mid + 1;
        else if (v[mid] > x &&
                v[mid] <= x)
            return mid;
        else if (v[mid] > x && mid == 0)
            return mid;
        else
            high = mid - 1;
    }
    return -1;
}
 
// function to calculate the number of ways to
// divide the array into three contiguous parts
static int CountContiguousParts(int []arr, int n)
{
    int count = 0; // initializing answer
 
    // Creating and filling prefix array
    int []prefix = new int[n];
    prefix[0] = arr[0];
    for (int i = 1; i < n; i++)
        prefix[i] = prefix[i - 1] + arr[i];
 
    // Total sum of elements is equal to last
    // value in prefix array.
    int total_sum = prefix[n - 1];
 
    // If sum of all the elements is not divisible
    // by 3, we can't divide array in 3 parts of
    // same sum.
    if (total_sum % 3 != 0)
        return 0;
 
    // Creating and filling suffix array
    int []suffix = new int[n];
    suffix[n - 1] = arr[n - 1];
    for (int i = n - 2; i >= 0; i--)
        suffix[i] = suffix[i + 1] + arr[i];
 
    // Storing all indexes with suffix
    // sum equal to total sum by 3.
    List v = new List();
    for (int i = 0; i < n; i++)
        if (suffix[i] == total_sum / 3)
            v.Add(i);
 
    // Traversing the prefix array and
    // doing binary search in above vector
    for (int i = 0; i < n; i++)
    {
        // We found a prefix with total_sum/3
        if (prefix[i] == total_sum / 3)
        {
            // Find first index in v[] which
            // is greater than i+1.
            int res = binarysearch(v, i + 1);
 
            if (res != -1)
                count += v.Count - res;
        }
    }
    return count;
}
 
// Driver Code
public static void Main(String[] args)
{
    int []arr = {1 , 2 , 3 , 0 , 3};
    int n = arr.Length;
    Console.WriteLine(CountContiguousParts(arr, n));
}
}
 
// This code is contributed by Rajput-Ji


Javascript


C
// C++ program to count the ways
// to break the array in 3 equal parts
// having equal sum.
#include 
using namespace std;
 
// Function to count the no of ways
int countways(int a[], int n)
{
    int cnt[n] = {0}, s = 0;
     
    // Calculating the sum of the array
    // and storing it in variable s
    for (int i = 0 ; i < n ; i++)
    {
        s += a[i];
    }
 
    // Checking s is divisible by 3 or not
    if (s % 3 != 0)
        return 0;
     
    // Calculating the sum of each part
    s /= 3;
     
    int ss = 0;
     
    // If the sum of elements from i-th to n-th
    // equals to sum of part putting 1 in cnt
    // array otherwise 0.
    for (int i = n-1; i >= 0 ; i--)
    {
        ss += a[i];
        if (ss == s)
            cnt[i] = 1;
    }
     
    // Calculating the cumulative sum
    // of the array cnt from the last index.
    for (int i = n-2 ; i >= 0 ; i--)
        cnt[i] += cnt[i + 1];
     
    int ans = 0;
    ss = 0;
     
    // Calculating answer using original
    // and cnt array.
    for (int i = 0 ; i+2 < n ; i++)
    {
        ss += a[i];
        if (ss == s)
            ans += cnt[i + 2];
    }
    return ans;
}
 
// Driver function
int main()
{
    int n = 5;
    int a[] = {1, 2, 3, 0, 3};
    cout << countways(a, n) << endl;
    return 0;
}


Java
// Java program to count the ways to
// break the array in 3 equal parts
// having equal sum.
import java.io.*;
 
class GFG {
     
    // Function to count the no of ways
    static int countways(int a[], int n)
    {
        int cnt[] = new int[n];
        int s = 0;
         
        // Calculating the sum of the array
        // and storing it in variable s
        for (int i = 0 ; i < n ; i++)
        {
            s += a[i];
        }
     
        // Checking s is divisible by 3 or not
        if (s % 3 != 0)
            return 0;
         
        // Calculating the sum of each part
        s /= 3;
         
        int ss = 0;
         
        // If the sum of elements from i-th to n-th
        // equals to sum of part then storing the number
          // of times possible in the cnt array.
        for (int i = n-1; i >= 0 ; i--)
        {
            ss += a[i];
            if (ss == s)
            {
                if(i == n-1)
                {
                  cnt[i] = 1;
                }
                  else
                {
                  cnt[i] = 1 + cnt[i+1];
                }
            }
        }
         
        int ans = 0;
        ss = 0;
         
        // Calculating answer using original
        // and cnt array.
        for (int i = 0 ; i+2 < n ; i++)
        {
            ss += a[i];
            if (ss == s)
                ans += cnt[i + 2];
        }
        return ans;
    }
     
    // Driver function
    public static void main (String[] args)
    {
        int n = 5;
        int a[] = {1, 2, 3, 0, 3};
        System.out.println(countways(a, n));
    }
}
 
// This code is contributed by anuj_67.


Python3
# Python3 program to count the ways
# to break the array in 3 equal parts
# having equal sum.
 
# Function to count the no of ways
def countways(a, n):
 
    cnt = [0 for i in range(n)]
    s = 0
 
    # Calculating the sum of the array
    # and storing it in variable s
    s = sum(a)
 
    # Checking s is divisible by 3 or not
    if (s % 3 != 0):
        return 0
 
    # Calculating the sum of each part
    s //= 3
 
    ss = 0
 
    # If the sum of elements from i-th
    # to n-th equals to sum of part
    # putting 1 in cnt array otherwise 0.
    for i in range(n - 1, -1, -1):
 
        ss += a[i]
        if (ss == s):
            cnt[i] = 1
 
    # Calculating the cumulative sum
    # of the array cnt from the last index.
    for i in range(n - 2, -1, -1):
        cnt[i] += cnt[i + 1]
 
    ans = 0
    ss = 0
 
    # Calculating answer using original
    # and cnt array.
    for i in range(0, n - 2):
        ss += a[i]
        if (ss == s):
            ans += cnt[i + 2]
 
    return ans
 
# Driver Code
n = 5
a = [1, 2, 3, 0, 3]
print(countways(a, n))
 
# This code is contributed
# by mohit kumar


C#
// C# program to count the ways to
// break the array in 3 equal parts
// having an equal sum.
using System;
 
class GFG
{
     
    // Function to count the no of ways
    static int countways(int[] a, int n)
    {
        int[] cnt = new int[n];
        int s = 0;
         
        // Calculating the sum of the array
        // and storing it in variable s
        for (int i = 0 ; i < n ; i++)
        {
            s += a[i];
        }
     
        // Checking s is divisible by 3 or not
        if (s % 3 != 0)
            return 0;
         
        // Calculating the sum of each part
        s /= 3;
         
        int ss = 0;
         
        // If the sum of elements from i-th to n-th
        // equals to sum of part putting 1 in cnt
        // array otherwise 0.
        for (int i = n - 1; i >= 0 ; i--)
        {
            ss += a[i];
            if (ss == s)
                cnt[i] = 1;
        }
         
        // Calculating the cumulative sum
        // of the array cnt from the last index.
        for (int i = n - 2 ; i >= 0 ; i--)
            cnt[i] += cnt[i + 1];
         
        int ans = 0;
        ss = 0;
         
        // Calculating answer using original
        // and cnt array.
        for (int i = 0 ; i + 2 < n ; i++)
        {
            ss += a[i];
            if (ss == s)
                ans += cnt[i + 2];
        }
        return ans;
    }
     
    // Driver code
    public static void Main ()
    {
        int n = 5;
        int[] a = {1, 2, 3, 0, 3};
        Console.Write(countways(a, n));
    }
}
 
// This code is contributed by Ita_c.


Javascript


输出:

2

时间复杂度为 O(n log n)

有效方法[ O(n) 解决方案]:

  1. 如果数组所有元素的总和不能被 3 整除,则返回 0。
  2. 很明显,每个连续部分的每个部分的总和将等于所有元素的总和除以 3。
  3. 让我们创建一个数组 cnt[ ],其中 cnt[ i ] 等于 1,如果从 i-th 到 n-th 的元素之和等于 Array_Sum/3 否则为 0。现在,从最后一个索引计算cnt数组的累积和.
  4. 因此,我们得到了非常简单的解决方案:对于初始数组 1…i 的每个前缀,总和等于 Array_Sum/3,我们需要添加到答案 sums[i+2]。

下面是上述方法的代码。

C

// C++ program to count the ways
// to break the array in 3 equal parts
// having equal sum.
#include 
using namespace std;
 
// Function to count the no of ways
int countways(int a[], int n)
{
    int cnt[n] = {0}, s = 0;
     
    // Calculating the sum of the array
    // and storing it in variable s
    for (int i = 0 ; i < n ; i++)
    {
        s += a[i];
    }
 
    // Checking s is divisible by 3 or not
    if (s % 3 != 0)
        return 0;
     
    // Calculating the sum of each part
    s /= 3;
     
    int ss = 0;
     
    // If the sum of elements from i-th to n-th
    // equals to sum of part putting 1 in cnt
    // array otherwise 0.
    for (int i = n-1; i >= 0 ; i--)
    {
        ss += a[i];
        if (ss == s)
            cnt[i] = 1;
    }
     
    // Calculating the cumulative sum
    // of the array cnt from the last index.
    for (int i = n-2 ; i >= 0 ; i--)
        cnt[i] += cnt[i + 1];
     
    int ans = 0;
    ss = 0;
     
    // Calculating answer using original
    // and cnt array.
    for (int i = 0 ; i+2 < n ; i++)
    {
        ss += a[i];
        if (ss == s)
            ans += cnt[i + 2];
    }
    return ans;
}
 
// Driver function
int main()
{
    int n = 5;
    int a[] = {1, 2, 3, 0, 3};
    cout << countways(a, n) << endl;
    return 0;
}

Java

// Java program to count the ways to
// break the array in 3 equal parts
// having equal sum.
import java.io.*;
 
class GFG {
     
    // Function to count the no of ways
    static int countways(int a[], int n)
    {
        int cnt[] = new int[n];
        int s = 0;
         
        // Calculating the sum of the array
        // and storing it in variable s
        for (int i = 0 ; i < n ; i++)
        {
            s += a[i];
        }
     
        // Checking s is divisible by 3 or not
        if (s % 3 != 0)
            return 0;
         
        // Calculating the sum of each part
        s /= 3;
         
        int ss = 0;
         
        // If the sum of elements from i-th to n-th
        // equals to sum of part then storing the number
          // of times possible in the cnt array.
        for (int i = n-1; i >= 0 ; i--)
        {
            ss += a[i];
            if (ss == s)
            {
                if(i == n-1)
                {
                  cnt[i] = 1;
                }
                  else
                {
                  cnt[i] = 1 + cnt[i+1];
                }
            }
        }
         
        int ans = 0;
        ss = 0;
         
        // Calculating answer using original
        // and cnt array.
        for (int i = 0 ; i+2 < n ; i++)
        {
            ss += a[i];
            if (ss == s)
                ans += cnt[i + 2];
        }
        return ans;
    }
     
    // Driver function
    public static void main (String[] args)
    {
        int n = 5;
        int a[] = {1, 2, 3, 0, 3};
        System.out.println(countways(a, n));
    }
}
 
// This code is contributed by anuj_67.

Python3

# Python3 program to count the ways
# to break the array in 3 equal parts
# having equal sum.
 
# Function to count the no of ways
def countways(a, n):
 
    cnt = [0 for i in range(n)]
    s = 0
 
    # Calculating the sum of the array
    # and storing it in variable s
    s = sum(a)
 
    # Checking s is divisible by 3 or not
    if (s % 3 != 0):
        return 0
 
    # Calculating the sum of each part
    s //= 3
 
    ss = 0
 
    # If the sum of elements from i-th
    # to n-th equals to sum of part
    # putting 1 in cnt array otherwise 0.
    for i in range(n - 1, -1, -1):
 
        ss += a[i]
        if (ss == s):
            cnt[i] = 1
 
    # Calculating the cumulative sum
    # of the array cnt from the last index.
    for i in range(n - 2, -1, -1):
        cnt[i] += cnt[i + 1]
 
    ans = 0
    ss = 0
 
    # Calculating answer using original
    # and cnt array.
    for i in range(0, n - 2):
        ss += a[i]
        if (ss == s):
            ans += cnt[i + 2]
 
    return ans
 
# Driver Code
n = 5
a = [1, 2, 3, 0, 3]
print(countways(a, n))
 
# This code is contributed
# by mohit kumar

C#

// C# program to count the ways to
// break the array in 3 equal parts
// having an equal sum.
using System;
 
class GFG
{
     
    // Function to count the no of ways
    static int countways(int[] a, int n)
    {
        int[] cnt = new int[n];
        int s = 0;
         
        // Calculating the sum of the array
        // and storing it in variable s
        for (int i = 0 ; i < n ; i++)
        {
            s += a[i];
        }
     
        // Checking s is divisible by 3 or not
        if (s % 3 != 0)
            return 0;
         
        // Calculating the sum of each part
        s /= 3;
         
        int ss = 0;
         
        // If the sum of elements from i-th to n-th
        // equals to sum of part putting 1 in cnt
        // array otherwise 0.
        for (int i = n - 1; i >= 0 ; i--)
        {
            ss += a[i];
            if (ss == s)
                cnt[i] = 1;
        }
         
        // Calculating the cumulative sum
        // of the array cnt from the last index.
        for (int i = n - 2 ; i >= 0 ; i--)
            cnt[i] += cnt[i + 1];
         
        int ans = 0;
        ss = 0;
         
        // Calculating answer using original
        // and cnt array.
        for (int i = 0 ; i + 2 < n ; i++)
        {
            ss += a[i];
            if (ss == s)
                ans += cnt[i + 2];
        }
        return ans;
    }
     
    // Driver code
    public static void Main ()
    {
        int n = 5;
        int[] a = {1, 2, 3, 0, 3};
        Console.Write(countways(a, n));
    }
}
 
// This code is contributed by Ita_c.

Javascript


输出:

2

时间复杂度: O(n)。