📌  相关文章
📜  将数组拆分为三个相等的子数组

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

将数组拆分为三个相等的子数组

考虑一个包含 n 个整数的数组 A。确定数组 A 是否可以分成三个连续的部分,使得每个部分的总和相等。如果是,则打印任何索引对(i, j) 使得 sum(arr[0..i]) = sum(arr[i+1..j]) = sum(arr[j+1..n-1 ]),否则打印 -1。
例子:

Input : arr[] = {1, 3, 4, 0, 4}
Output : (1, 2)
Sum of subarray arr[0..1] is equal to
sum of subarray arr[2..3] and also to
sum of subarray arr[4..4]. The sum is 4. 

Input : arr[] = {2, 3, 4}
Output : -1
No three subarrays exist which have equal
sum.

一个简单的解决方案是首先找到所有子数组,将这些子数组的和与它们的起点和终点存储起来,然后找到三个不相交且总和相等的连续子数组。该解决方案的时间复杂度将是二次的。
一个有效的解决方案是首先找到所有数组元素的总和 S。检查这个总和是否可以被 3 整除。这是因为如果 sum 不可整除,则 sum 不能分成三个相等的和集。如果有三个连续的子数组和相等,则每个子数组的和为 S/3。假设所需的索引对是 (i, j),使得 sum(arr[0..i]) = sum(arr[i+1..j]) = S/3。还有 sum(arr[0..i]) = preSum[i] 和 sum(arr[i+1..j]) = preSum[j] – preSum[i]。这给出了 preSum[i] = preSum[j] – preSum[i] = S/3。这给出了 preSum[j] = 2*preSum[i]。因此,问题简化为找到两个索引 i 和 j,使得 preSum[i] = S/3 和 preSum[j] = 2*(S/3)。
为了找到这两个索引,遍历数组并将总和存储到变量 preSum 中的当前元素。检查 preSum 是否等于 S/3 和 2*(S/3)。
执行:

C++
// CPP program to determine if array arr[]
// can be split into three equal sum sets.
#include 
using namespace std;
 
// Function to determine if array arr[]
// can be split into three equal sum sets.
int findSplit(int arr[], int n)
{
    int i;
 
    // variable to store prefix sum
    int preSum = 0;
 
    // variables to store indices which
    // have prefix sum divisible by S/3.
    int ind1 = -1, ind2 = -1;
 
    // variable to store sum of
    // entire array.
    int S;
 
    // Find entire sum of the array.
    S = arr[0];
    for (i = 1; i < n; i++)
        S += arr[i];
 
    // Check if array can be split in
    // three equal sum sets or not.
    if(S % 3 != 0)
        return 0;
     
    // Variables to store sum S/3
    // and 2*(S/3).
    int S1 = S / 3;
    int S2 = 2 * S1;
 
      // Loop until second last index
    // as S2 should not be at the last
      for (i = 0; i < n-1; i++)
    {
        preSum += arr[i];
         
        // If prefix sum is equal to S/3
        // store current index.
        if (preSum == S1 && ind1 == -1)
            ind1 = i;
         
        // If prefix sum is equal to 2* (S/3)
        // store current index.
        else if(preSum  == S2 && ind1 != -1)
        {
            ind2 = i;
             
            // Come out of the loop as both the
            // required indices are found.
            break;
        }
    }
 
    // If both the indices are found
    // then print them.
    if (ind1 != -1 && ind2 != -1)
    {
        cout << "(" << ind1 << ", "
                                << ind2 << ")";
        return 1;
    }
 
    // If indices are not found return 0.
    return 0;
}
 
// Driver code
int main()
{
    int arr[] =  { 1, 3, 4, 0, 4 };
    int n = sizeof(arr) / sizeof(arr[0]);
    if (findSplit(arr, n) == 0)
        cout << "-1";
    return 0;
}


Java
// Java program to determine if array arr[]
// can be split into three equal sum sets.
import java.io.*;
import java.util.*;
 
public class GFG {
     
    // Function to determine if array arr[]
    // can be split into three equal sum sets.
    static int findSplit(int []arr, int n)
    {
        int i;
     
        // variable to store prefix sum
        int preSum = 0;
     
        // variables to store indices which
        // have prefix sum divisible by S/3.
        int ind1 = -1, ind2 = -1;
     
        // variable to store sum of
        // entire array.
        int S;
     
        // Find entire sum of the array.
        S = arr[0];
        for (i = 1; i < n; i++)
            S += arr[i];
     
        // Check if array can be split in
        // three equal sum sets or not.
        if(S % 3 != 0)
            return 0;
         
        // Variables to store sum S/3
        // and 2*(S/3).
        int S1 = S / 3;
        int S2 = 2 * S1;
       
        // Loop until second last index
        // as S2 should not be at the last
        for (i = 0; i < n-1; i++)
        {
            preSum += arr[i];
             
        // If prefix sum is equal to S/3
        // store current index.
            if (preSum == S1 && ind1 == -1)
                ind1 = i;
             
        // If prefix sum is equal to 2*(S/3)
        // store current index.
            else if(preSum == S2 && ind1 != -1)
            {
                ind2 = i;
                 
                // Come out of the loop as both the
                // required indices are found.
                break;
            }
        }
     
        // If both the indices are found
        // then print them.
        if (ind1 != -1 && ind2 != -1)
        {
            System.out.print("(" + ind1 + ", "
                            + ind2 + ")");
            return 1;
        }
     
        // If indices are not found return 0.
        return 0;
    }
     
    // Driver code
    public static void main(String args[])
    {
        int []arr = { 1, 3, 4, 0, 4 };
        int n = arr.length;
        if (findSplit(arr, n) == 0)
            System.out.print("-1");
    }
}
 
// This code is contributed by Manish Shaw
// (manishshaw1)


Python3
# Python3 program to determine if array arr[]
# can be split into three equal sum sets.
 
# Function to determine if array arr[]
# can be split into three equal sum sets.
def findSplit(arr, n):
    # variable to store prefix sum
    preSum = 0
 
    # variables to store indices which
    # have prefix sum divisible by S/3.
    ind1 = -1
    ind2 = -1
 
    # variable to store sum of
    # entire array. S
 
    # Find entire sum of the array.
    S = arr[0]
    for i in range(1, n):
        S += arr[i]
 
    # Check if array can be split in
    # three equal sum sets or not.
    if(S % 3 != 0):
        return 0
     
    # Variables to store sum S/3
    # and 2*(S/3).
    S1 = S / 3
    S2 = 2 * S1
 
    # Loop until second last index
    # as S2 should not be at the last
    for i in range(0,n-1):
        preSum += arr[i]
         
        # If prefix sum is equal to S/3
        # store current index.
        if (preSum == S1 and ind1 == -1):
            ind1 = i
        # If prefix sum is equal to 2*(S/3)
        # store current index.       
        elif(preSum == S2 and ind1 != -1):
            ind2 = i
             
            # Come out of the loop as both the
            # required indices are found.
            break   
 
    # If both the indices are found
    # then print them.
    if (ind1 != -1 and ind2 != -1):
        print ("({}, {})".format(ind1,ind2))
        return 1
     
    # If indices are not found return 0.
    return 0
 
# Driver code
arr = [ 1, 3, 4, 0, 4 ]
n = len(arr)
if (findSplit(arr, n) == 0) :
    print ("-1")
# This code is contributed by Manish Shaw
# (manishshaw1)


C#
// C# program to determine if array arr[]
// can be split into three equal sum sets.
using System;
using System.Collections.Generic;
 
class GFG {
     
    // Function to determine if array arr[]
    // can be split into three equal sum sets.
    static int findSplit(int []arr, int n)
    {
        int i;
     
        // variable to store prefix sum
        int preSum = 0;
     
        // variables to store indices which
        // have prefix sum divisible by S/3.
        int ind1 = -1, ind2 = -1;
     
        // variable to store sum of
        // entire array.
        int S;
     
        // Find entire sum of the array.
        S = arr[0];
        for (i = 1; i < n; i++)
            S += arr[i];
     
        // Check if array can be split in
        // three equal sum sets or not.
        if(S % 3 != 0)
            return 0;
         
        // Variables to store sum S/3
        // and 2*(S/3).
        int S1 = S / 3;
        int S2 = 2 * S1;
     
        // Loop until second last index
        // as S2 should not be at the last
        for (i = 0; i < n-1; i++)
        {
            preSum += arr[i];
             
        // If prefix sum is equal to S/3
        // store current index.
            if (preSum ==  S1 && ind1 == -1)
                ind1 = i;
             
        // If prefix sum is equal to S/3
        // store current index.
            else if(preSum == S2 && ind1 != -1)
            {
                ind2 = i;
                 
                // Come out of the loop as both the
                // required indices are found.
                break;
            }
        }
     
        // If both the indices are found
        // then print them.
        if (ind1 != -1 && ind2 != -1)
        {
            Console.Write("(" + ind1 + ", "
                             + ind2 + ")");
            return 1;
        }
     
        // If indices are not found return 0.
        return 0;
    }
     
    // Driver code
    public static void Main()
    {
        int []arr = { 1, 3, 4, 0, 4 };
        int n = arr.Length;
        if (findSplit(arr, n) == 0)
            Console.Write("-1");
    }
}
 
// This code is contributed by Manish Shaw
// (manishshaw1)


PHP


Javascript


输出
(1, 2)

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