📌  相关文章
📜  将数组分成三个相等的和段

📅  最后修改于: 2021-04-22 09:04:58             🧑  作者: Mango

给定一个由n个整数组成的数组,我们必须将该数组划分为三个段,以使所有段的总和相等。细分总和是细分中所有元素的总和。

例子:

Input :  1, 3, 6, 2, 7, 1, 2, 8
Output : [1, 3, 6], [2, 7, 1], [2, 8]

Input :  7, 6, 1, 7
Output :  [7], [6, 1], [7]

Input :  7, 6, 2, 7
Output : Cannot divide the array into segments

一个简单的解决方案是考虑所有索引对,并检查每一对索引是否将数组分为三个相等的部分。如果是,则返回true。该解决方案的时间复杂度为O(n 2 )

一种有效的方法是使用两个辅助数组并将前缀和后缀数组总和分别存储在这些数组中。然后,我们使用两个指针的方法,其中变量“ i”指向前缀数组的开始,变量“ j”指向后缀数组的结尾。如果pre [i]> suf [j],则递减’j’,否则递减’i’。
我们维护一个变量,其值是数组的总和,并且每当遇到pre [i] = total_sum / 3或suf [j] = total_sum / 3时,我们分别将i或j的值存储为段边界。

C++
// C++ implementation of the approach
#include
using namespace std;
  
// First segment's end index
static int pos1 = -1; 
  
// Third segment's start index
static int pos2 = -1; 
  
// This function returns true if the array 
// can be divided into three equal sum segments
bool equiSumUtil(int arr[],int n)
{
  
    // Prefix Sum Array
    int pre[n];
    int sum = 0;
    for (int i = 0; i < n; i++)
    {
        sum += arr[i];
        pre[i] = sum;
    }
  
    // Suffix Sum Array
    int suf[n];
    sum = 0;
    for (int i = n - 1; i >= 0; i--) 
    {
        sum += arr[i];
        suf[i] = sum;
    }
  
    // Stores the total sum of the array
    int total_sum = sum; 
  
    int i = 0, j = n - 1;
    while (i < j - 1) 
    {
  
        if (pre[i] == total_sum / 3)
        {
                pos1 = i;
        }
  
        if (suf[j] == total_sum / 3)
        {
            pos2 = j;
        }
  
        if (pos1 != -1 && pos2 != -1) 
        {
  
            // We can also take pre[pos2 - 1] - pre[pos1] ==
            // total_sum / 3 here.
            if (suf[pos1 + 1] - suf[pos2] == total_sum / 3) 
            { 
                return true;
            }
            else 
            {
                return false;
            }
        }
  
        if (pre[i] < suf[j]) 
        {
            i++;
        }
        else 
        {
            j--;
        }
    }
  
    return false;
}
  
void equiSum(int arr[],int n)
{
    bool ans = equiSumUtil(arr,n);
    if (ans) 
    {
  
        cout << "First Segment : ";
        for (int i = 0; i <= pos1; i++) 
        {
            cout << arr[i] << " ";
        }
  
        cout << endl;
  
        cout << "Second Segment : ";
        for (int i = pos1 + 1; i < pos2; i++) 
        {
            cout << arr[i] << " ";
        }
  
        cout << endl;
  
        cout << "Third Segment : ";
        for (int i = pos2; i < n; i++)
        {
            cout << arr[i] << " ";
        }
  
        cout<


Java
public class Main {
  
    //  First segment's end index
    public static int pos1 = -1; 
  
    //  Third segment's start index
    public static int pos2 = -1; 
  
    // This function returns true if the array 
    // can be divided into three equal sum segments
    public static boolean equiSumUtil(int[] arr)
    {
        int n = arr.length;
  
        // Prefix Sum Array
        int[] pre = new int[n];
        int sum = 0;
        for (int i = 0; i < n; i++) {
            sum += arr[i];
            pre[i] = sum;
        }
  
        // Suffix Sum Array
        int[] suf = new int[n];
        sum = 0;
        for (int i = n - 1; i >= 0; i--) {
            sum += arr[i];
            suf[i] = sum;
        }
  
        // Stores the total sum of the array
        int total_sum = sum; 
  
        int i = 0, j = n - 1;
        while (i < j - 1) {
  
            if (pre[i] == total_sum / 3) {
                pos1 = i;
            }
  
            if (suf[j] == total_sum / 3) {
                pos2 = j;
            }
  
            if (pos1 != -1 && pos2 != -1) {
  
                // We can also take pre[pos2 - 1] - pre[pos1] ==
                // total_sum / 3 here.
                if (suf[pos1 + 1] - suf[pos2] == total_sum / 3) { 
                    return true;
                }
                else {
                    return false;
                }
            }
  
            if (pre[i] < suf[j]) {
                i++;
            }
            else {
                j--;
            }
        }
  
        return false;
    }
  
    public static void equiSum(int[] arr)
    {
        boolean ans = equiSumUtil(arr);
        if (ans) {
  
            System.out.print("First Segment : ");
            for (int i = 0; i <= pos1; i++) {
                System.out.print(arr[i] + " ");
            }
  
            System.out.println();
  
            System.out.print("Second Segment : ");
            for (int i = pos1 + 1; i < pos2; i++) {
                System.out.print(arr[i] + " ");
            }
  
            System.out.println();
  
            System.out.print("Third Segment : ");
            for (int i = pos2; i < arr.length; i++) {
                System.out.print(arr[i] + " ");
            }
  
            System.out.println();
        }
        else {
            System.out.println("Array cannot be " + 
            "divided into three equal sum segments");
        }
    }
    public static void main(String[] args)
    {
        int[] arr = { 1, 3, 6, 2, 7, 1, 2, 8 };
        equiSum(arr);
    }
}


Python3
# Python3 implementation of the given approach
  
# This function returns true if the array 
# can be divided into three equal sum segments
def equiSumUtil(arr, pos1, pos2):
  
    n = len(arr);
  
    # Prefix Sum Array
    pre = [0] * n;
    sum = 0;
    for i in range(n): 
        sum += arr[i];
        pre[i] = sum;
  
    # Suffix Sum Array
    suf = [0] * n;
    sum = 0;
    for i in range(n - 1, -1, -1): 
        sum += arr[i];
        suf[i] = sum;
  
    # Stores the total sum of the array
    total_sum = sum; 
  
    i = 0;
    j = n - 1;
    while (i < j - 1): 
  
        if (pre[i] == total_sum // 3): 
            pos1 = i;
  
        if (suf[j] == total_sum // 3): 
            pos2 = j;
  
        if (pos1 != -1 and pos2 != -1): 
  
            # We can also take pre[pos2 - 1] - pre[pos1] ==
            # total_sum / 3 here.
            if (suf[pos1 + 1] - 
                suf[pos2] == total_sum // 3):
                return [True, pos1, pos2];
            else:
                return [False, pos1, pos2];
  
        if (pre[i] < suf[j]): 
            i += 1;
        else:
            j -= 1;
  
    return [False, pos1, pos2];
  
def equiSum(arr):
  
    pos1 = -1;
    pos2 = -1;
    ans = equiSumUtil(arr, pos1, pos2);
    pos1 = ans[1];
    pos2 = ans[2];
    if (ans[0]): 
        print("First Segment : ", end = "");
        for i in range(pos1 + 1): 
            print(arr[i], end = " ");
  
        print("");
  
        print("Second Segment : ", end = "");
        for i in range(pos1 + 1, pos2): 
            print(arr[i], end = " ");
  
        print("");
  
        print("Third Segment : ", end = "");
        for i in range(pos2, len(arr)): 
            print(arr[i], end = " ");
  
        print("");
    else:
        println("Array cannot be divided into",
                "three equal sum segments");
  
# Driver Code
arr = [1, 3, 6, 2, 7, 1, 2, 8 ];
equiSum(arr);
  
# This code is contributed by mits


C#
// C# implementation of the approach
using System;
      
class GFG 
{
  
    // First segment's end index
    public static int pos1 = -1; 
  
    // Third segment's start index
    public static int pos2 = -1; 
  
    // This function returns true if the array 
    // can be divided into three equal sum segments
    public static bool equiSumUtil(int[] arr)
    {
        int n = arr.Length;
  
        // Prefix Sum Array
        int[] pre = new int[n];
        int sum = 0,i;
        for (i = 0; i < n; i++) 
        {
            sum += arr[i];
            pre[i] = sum;
        }
  
        // Suffix Sum Array
        int[] suf = new int[n];
        sum = 0;
        for (i = n - 1; i >= 0; i--)
        {
            sum += arr[i];
            suf[i] = sum;
        }
  
        // Stores the total sum of the array
        int total_sum = sum; 
  
        int j = n - 1;
        i = 0;
        while (i < j - 1) 
        {
  
            if (pre[i] == total_sum / 3) 
            {
                pos1 = i;
            }
  
            if (suf[j] == total_sum / 3) 
            {
                pos2 = j;
            }
  
            if (pos1 != -1 && pos2 != -1) 
            {
  
                // We can also take pre[pos2 - 1] - pre[pos1] ==
                // total_sum / 3 here.
                if (suf[pos1 + 1] - suf[pos2] == total_sum / 3) 
                { 
                    return true;
                }
                else 
                {
                    return false;
                }
            }
  
            if (pre[i] < suf[j]) 
            {
                i++;
            }
            else 
            {
                j--;
            }
        }
  
        return false;
    }
  
    public static void equiSum(int[] arr)
    {
        bool ans = equiSumUtil(arr);
        if (ans)
        {
  
            Console.Write("First Segment : ");
            for (int i = 0; i <= pos1; i++)
            {
                Console.Write(arr[i] + " ");
            }
  
            Console.WriteLine();
  
            Console.Write("Second Segment : ");
            for (int i = pos1 + 1; i < pos2; i++) 
            {
                Console.Write(arr[i] + " ");
            }
  
            Console.WriteLine();
  
            Console.Write("Third Segment : ");
            for (int i = pos2; i < arr.Length; i++) 
            {
                Console.Write(arr[i] + " ");
            }
  
            Console.WriteLine();
        }
        else 
        {
            Console.WriteLine("Array cannot be " + 
            "divided into three equal sum segments");
        }
    }
    public static void Main(String[] args)
    {
        int[] arr = { 1, 3, 6, 2, 7, 1, 2, 8 };
        equiSum(arr);
    }
}
  
// This code contributed by Rajput-Ji


PHP
= 0; $i--) 
    {
        $sum += $arr[$i];
        $suf[$i] = $sum;
    }
  
    // Stores the total sum of the array
    $total_sum = $sum; 
  
    $i = 0;
    $j = $n - 1;
    while ($i < $j - 1) 
    {
  
        if ($pre[$i] == $total_sum / 3) 
        {
            $pos1 = $i;
        }
  
        if ($suf[$j] == $total_sum / 3) 
        {
            $pos2 = $j;
        }
  
        if ($pos1 != -1 && $pos2 != -1) 
        {
  
            // We can also take pre[pos2 - 1] - pre[pos1] ==
            // total_sum / 3 here.
            if ($suf[$pos1 + 1] - 
                     $suf[$pos2] == $total_sum / 3)
            { 
                return true;
            }
            else 
            {
                return false;
            }
        }
  
        if ($pre[$i] < $suf[$j]) 
        {
            $i++;
        }
        else
        {
            $j--;
        }
    }
  
    return false;
}
  
function equiSum($arr)
{
    global $pos2,$pos1;
    $ans = equiSumUtil($arr);
    if ($ans) 
    {
  
        print("First Segment : ");
        for ($i = 0; $i <= $pos1; $i++) 
        {
            print($arr[$i] . " ");
        }
  
        print("\n");
  
        print("Second Segment : ");
        for ($i = $pos1 + 1; $i < $pos2; $i++) 
        {
            print($arr[$i] . " ");
        }
  
        print("\n");
  
        print("Third Segment : ");
        for ($i = $pos2; $i < count($arr); $i++) 
        {
            print($arr[$i] . " ");
        }
  
        print("\n");
    }
    else 
    {
        println("Array cannot be divided into ", 
                "three equal sum segments");
    }
}
  
// Driver Code
$arr = array(1, 3, 6, 2, 7, 1, 2, 8 );
equiSum($arr);
  
// This code is contributed by mits
?>


输出:
First Segment : 1 3 6 
Second Segment : 2 7 1 
Third Segment : 2 8

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