📌  相关文章
📜  数组的最佳划分为四个部分

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

数组的最佳划分为四个部分

给定一个包含 n 个非负整数的数组。从数组中选择三个索引,即(0 <= index_1 <= index_2<= index_3 <= n)来生成四个子集,使得sum(0, index_1) – sum(index_1, index_2) + sum(index_2, index_3 ) – sum(index_3, n)是可能的最大值。
这里,两个索引说 l 和 r 意味着 sum(l, r) 将是从 l 到 r 不包括在内的位置上的所有子集数的总和(不计算第 l 个元素,计算第 r 个元素)。例如,如果 arr = {-5, 3, 9, 4},则 sum(0, 1) = -5, sum(0, 2) = -2, sum(1, 4) = 16 和 sum(i , i) = 0 对于从 0 到 4 的每个 i。对于索引 l 和 r 保持 0 <= l <= r <= n。数组中的索引从 0 开始编号。
例子:

Input : arr = {-1, 2, 3}
Output : 0 1 3   
Here, sum(0, 0) = 0
      sum(0, 1) = -1
      sum(1, 3) = 2 + 3 = 5
      sum(3, 3) = 0
Therefore , sum(0, 0) - sum(0, 1) + sum(1, 3) - sum(3, 3) = 4
which is maximum.

Input : arr = {0, 0, -1, 0}
Output : 0 0 0
Here, sum(0, 0) - sum(0, 0) + sum(0, 0) - sum(0, 0) = 0
which is maximum possible.

想象一下相同的任务,但总和没有第一项。由于数组的总和是固定的,因此最好的第二段应该是总和最大的段。这可以用前缀总和在 O(n) 中解决。当调用在位置 i 处结束的最佳段时,取从 0 到 i 的最小前缀总和(从要减去最小数字的总和中)。
现在让我们遍历第一个段的所有可能末端,并在没有这个段的数组上解决上面的任务。

C++
// CPP program to find three indices
#include 
#define max 50009
using namespace std;
 
// Function to find required indices.
void find_Indices(int arr[], int n){
    int sum[max], k;
    int index_1, index_2, index_3, index;
     
    // calculating prefix sum from
    // 1 to i for each i.
    for (int i = 1, k = 0; i <= n; i++)
        sum[i] = sum[i-1] + arr[k++];   
     
    long long ans = -(1e15);
    index_1 = index_2 = index_3 = -1;
 
    // iterating the loop from 0 to n
    // for all possibilities.
    for (int l = 0; l <= n; l++) {
        int index = 0;
        long long vmin = (1e15);
 
        // Here, we recalling the best
        // segment to end at position i.
        for (int r = l; r <= n; r++) {
 
            // taking the minimal prefix
            // sum from 0 to i inclusive.
            if (sum[r] < vmin) {
                vmin = sum[r];
                index = r;
            }
                         
            // calculating the indices.
            if (sum[l] + sum[r] - vmin > ans)
            {
                ans = sum[l] + sum[r] - vmin;
                index_1 = l;
                index_2 = index;
                index_3 = r;
            }
        }
    }
 
    // Required indices.
    printf("%d %d %d", index_1, index_2, index_3);
}
 
// Driver function
int main() {
    int arr[] = {-1, 2, 3};
    int n = sizeof(arr)/sizeof(arr[0]);
    find_Indices(arr, n);
}


Java
// Java program to find three indices
class GFG {
     
    static final int max = 50009;
     
    // Function to find required indices.
    static void find_Indices(int arr[], int n)
    {
         
        int sum[] = new int[max];
        int index_1, index_2, index_3, index;
        int k, i;
 
        // calculating prefix sum from
        // 1 to i for each i.
        for (i = 1, k = 0; i <= n; i++)
            sum[i] = sum[i - 1] + arr[k++];
 
        double ans = -(1e15);
        index_1 = index_2 = index_3 = -1;
 
        // iterating the loop from 0 to n
        // for all possibilities.
        for (int l = 0; l <= n; l++) {
            index = 0;
            double vmin = (1e15);
 
            // Here, we recalling the best
            // segment to end at position i.
            for (int r = l; r <= n; r++) {
 
                // taking the minimal prefix
                // sum from 0 to i inclusive.
                if (sum[r] < vmin)
                {
                    vmin = sum[r];
                    index = r;
                }
 
                // calculating the indices.
                if (sum[l] + sum[r] - vmin > ans)
                {
                    ans = sum[l] + sum[r] - vmin;
                    index_1 = l;
                    index_2 = index;
                    index_3 = r;
                }
            }
        }
 
        // Required indices.
        System.out.print(index_1 + " " + index_2 +
                                    " " + index_3);
    }
     
    // Driver function.
    public static void main(String[] args)
    {
        int arr[] = { -1, 2, 3 };
        int n = arr.length;
 
        find_Indices(arr, n);
    }
}
 
// This code is contributed by Anant Agarwal.


Python3
# Python program to
# find three indices
 
max = 50009
 
# Function to find
# required indices.
def find_Indices(arr, n):
 
    sum=[0 for i in range(max)]
      
    # calculating prefix sum from
    # 1 to i for each i.
    k=0
    for i in range(1,n+1):
        sum[i] = sum[i-1] + arr[k];
        k+=1
      
    ans = -(1e15)
    index_1 = index_2 = index_3 = -1
  
    # iterating the loop from 0 to n
    # for all possibilities.
    for l in range(n+1):
        index = 0
        vmin = (1e15)
  
        # Here, we recalling the best
        # segment to end at position i.
        for r in range(l,n+1):
  
             
            # taking the minimal prefix
            # sum from 0 to i inclusive.
            if (sum[r] < vmin):
                vmin = sum[r]
                index = r
             
                          
            # calculating the indices.
            if (sum[l] + sum[r] - vmin > ans):
             
                ans = sum[l] + sum[r] - vmin
                index_1 = l
                index_2 = index
                index_3 = r
         
    # Required indices.
    print(index_1," ", index_2," ", index_3)
  
# Driver function
 
arr = [-1, 2, 3]
n = len(arr)
find_Indices(arr, n)
 
# This code is contributed
# by Anant Agarwal.


C#
// C# program to find three indices
using System;
 
class GFG {
     
    static int max = 50009;
     
    // Function to find required indices.
    static void find_Indices(int []arr, int n)
    {
         
        int []sum = new int[max];
        int index_1, index_2, index_3, index;
        int k, i;
 
        // calculating prefix sum from
        // 1 to i for each i.
        for (i = 1, k = 0; i <= n; i++)
            sum[i] = sum[i - 1] + arr[k++];
 
        double ans = -(1e15);
        index_1 = index_2 = index_3 = -1;
 
        // iterating the loop from 0 to n
        // for all possibilities.
        for (int l = 0; l <= n; l++) {
            index = 0;
            double vmin = (1e15);
 
            // Here, we recalling the best
            // segment to end at position i.
            for (int r = l; r <= n; r++) {
 
                // taking the minimal prefix
                // sum from 0 to i inclusive.
                if (sum[r] < vmin)
                {
                    vmin = sum[r];
                    index = r;
                }
 
                // calculating the indices.
                if (sum[l] + sum[r] - vmin > ans)
                {
                    ans = sum[l] + sum[r] - vmin;
                    index_1 = l;
                    index_2 = index;
                    index_3 = r;
                }
            }
        }
 
        // Required indices.
        Console.WriteLine(index_1 + " " + index_2 +
                                    " " + index_3);
    }
     
    // Driver function.
    public static void Main()
    {
        int []arr = { -1, 2, 3 };
        int n = arr.Length;
 
        find_Indices(arr, n);
    }
}
 
// This code is contributed by vt_m.


PHP
 $ans)
            {
                $ans = $sum[$l] +
                       $sum[$r] - $vmin;
                $index_1 = $l;
                $index_2 = $index;
                $index_3 = $r;
            }
        }
    }
 
    // Required indices.
    echo($index_1." ".$index_2.
                  " ".$index_3." ");
}
 
// Driver Code
$arr = array(-1, 2, 3);
$n = count($arr);
find_Indices($arr, $n);
 
// This code is contributed by
// Manish Shaw(manishshaw1)
?>


Javascript


输出:

0 1 3

时间复杂度: O(n^2).