📜  使用前缀和的 O(n) 中的最大子数组和

📅  最后修改于: 2021-09-22 09:52:54             🧑  作者: Mango

给定一个正整数和负整数数组,找出该数组中的最大子数组和。

例子:

Input1 : arr = {-2, -3, 4, -1, -2, 1, 5, -3}
Output1 : 7

Input2 : arr = {4, -8, 9, -4, 1, -8, -1, 6}
Output2 : 9

Kadane 算法在线性时间内使用动态规划方法解决了这个问题。这是另一种使用动态规划和前缀总和来找出线性时间内最大子阵列总和的方法。
先决条件:前缀和数组

执行:
1. 计算输入数组的前缀和。
2. 初始化:min_prefix_sum = 0, res = -infinite
3. 保持 i = 0 到 n 的循环。 (n 是输入数组的大小)。
a) cand = prefix_sum[i] – mini
b) 如果cand大于res(到目前为止的最大子数组和),则通过cand 更新res。
c) 如果 prefix_sum[i] 小于 min_prefix_sum(到目前为止的最小前缀和),则通过 prefix_sum[i] 更新 min_prefix_sum。
4. 返回资源。
参考: k 最大和问题的算法和 k 最大子阵列问题的 VLSI 算法

C++
// C++ program to find out maximum subarray
// sum in linear time using prefix sum.
#include 
#include 
using namespace std;
 
// Function to compute maximum subarray
// sum in linear time.
int maximumSumSubarray(int arr[], int n)
{
    // Initialize minimum prefix sum to 0.
    int min_prefix_sum = 0;
 
    // Initialize maximum subarray sum so
    // far to -infinity.
    int res = numeric_limits::min();
 
    // Initialize and compute the prefix
    // sum array.
    int prefix_sum[n];
    prefix_sum[0] = arr[0];
    for (int i = 1; i < n; i++)
        prefix_sum[i] = prefix_sum[i - 1] + arr[i];       
 
    // loop through the array, keep track
    // of minimum prefix sum so far and
    // maximum subarray sum.
    for (int i = 0; i < n; i++) {
        res = max(res, prefix_sum[i] -
                       min_prefix_sum);
        min_prefix_sum = min(min_prefix_sum,
                             prefix_sum[i]);
    }
     
    return res;
}
 
// Driver Program
int main()
{
    // Test case 1
    int arr1[] = { -2, -3, 4, -1, -2, 1, 5, -3 };
    int n1 = sizeof(arr1) / sizeof(arr1[0]);
    cout << maximumSumSubarray(arr1, n1) << endl;
 
    // Test case 2
    int arr2[] = { 4, -8, 9, -4, 1, -8, -1, 6 };
    int n2 = sizeof(arr2) / sizeof(arr2[0]);
    cout << maximumSumSubarray(arr2, n2);
 
    return 0;
}


Java
// Java program to find
// out maximum subarray
// sum in linear time
// using prefix sum.
 
class GFG
{
    // Function to compute maximum
    // subarray sum in linear time.
    static int maximumSumSubarray(int arr[], int n)
    {
        // Initialize minimum
        // prefix sum to 0.
        int min_prefix_sum = 0;
     
        // Initialize maximum subarray
        // sum so far to -infinity.
        int res = Integer.MIN_VALUE;
     
        // Initialize and compute
        // the prefix sum array.
        int prefix_sum[] = new int[n];
        prefix_sum[0] = arr[0];
        for (int i = 1; i < n; i++)
            prefix_sum[i] = prefix_sum[i - 1]
                            + arr[i];    
     
        // loop through the array, keep
        // track of minimum prefix sum so
        // far and maximum subarray sum.
        for (int i = 0; i < n; i++)
        {
            res = Math.max(res, prefix_sum[i] -
                           min_prefix_sum);
            min_prefix_sum = Math.min(min_prefix_sum,
                                     prefix_sum[i]);
        }
         
        return res;
    }
     
    // Driver Program
    public static void main (String[] args)
    {
        // Test case 1
        int arr1[] = { -2, -3, 4, -1, -2, 1, 5, -3 };
        int n1 = arr1.length;
        System.out.println(maximumSumSubarray(arr1, n1));
     
        // Test case 2
        int arr2[] = { 4, -8, 9, -4, 1, -8, -1, 6 };
        int n2 = arr2.length;
        System.out.println(maximumSumSubarray(arr2, n2));
    }
}
 
// This code is contributed by Ansu Kumari.


Python3
# Python3 program to find out
# maximum subarray sum in
# linear time using prefix
# sum.
import math
 
# Function to compute maximum
# subarray sum in linear time.
def maximumSumSubarray(arr, n):
     
    # Initialize minimum prefix
    # sum to 0.
    min_prefix_sum = 0
 
    # Initialize maximum subarray
    # sum so far to -infinity.
    res = -math.inf
 
    # Initialize and compute the
    # prefix sum array.
    prefix_sum = []
    prefix_sum.append(arr[0])
     
    for i in range(1, n):
        prefix_sum.append(prefix_sum[i - 1] + arr[i])    
 
    # loop through the array keep
    # track of minimum prefix sum
    # so far and maximum subarray
    # sum.
    for i in range(n):
         
        res = max(res, prefix_sum[i] - min_prefix_sum)
        min_prefix_sum = min(min_prefix_sum, prefix_sum[i])
     
    return res
 
# Driver Program
 
# Test case 1
arr1 = [ -2, -3, 4, -1, -2, 1, 5, -3 ]
n1 = len(arr1)
print(maximumSumSubarray(arr1, n1))
 
# Test case 2
arr2 = [ 4, -8, 9, -4, 1, -8, -1, 6 ]
n2 = len(arr2)
print(maximumSumSubarray(arr2, n2))
 
# This code is contributed by Ansu Kuamri.


C#
// C# program to find
// out maximum subarray
// sum in linear time
// using prefix sum.
using System;
 
class GFG
{
    // Function to compute maximum
    // subarray sum in linear time.
    static int maximumSumSubarray(int []arr, int n)
    {
        // Initialize minimum
        // prefix sum to 0.
        int min_prefix_sum = 0;
     
        // Initialize maximum subarray
        // sum so far to -infinity.
        int res = int.MinValue;
     
        // Initialize and compute
        // the prefix sum array.
        int []prefix_sum = new int[n];
        prefix_sum[0] = arr[0];
        for (int i = 1; i < n; i++)
            prefix_sum[i] = prefix_sum[i - 1]
                            + arr[i];
     
        // loop through the array, keep
        // track of minimum prefix sum so
        // far and maximum subarray sum.
        for (int i = 0; i < n; i++)
        {
            res = Math.Max(res, prefix_sum[i] -
                        min_prefix_sum);
            min_prefix_sum = Math.Min(min_prefix_sum,
                                    prefix_sum[i]);
        }
         
        return res;
    }
     
    // Driver Program
    public static void Main ()
    {
        // Test case 1
        int []arr1 = { -2, -3, 4, -1, -2, 1, 5, -3 };
        int n1 = arr1.Length;
        Console.WriteLine(maximumSumSubarray(arr1, n1));
     
        // Test case 2
        int []arr2 = { 4, -8, 9, -4, 1, -8, -1, 6 };
        int n2 = arr2.Length;
        Console.WriteLine(maximumSumSubarray(arr2, n2));
    }
}
 
// This code is contributed by vt_m.


PHP


Javascript


输出 :

7
9

更简单有效的解决方案
时间复杂度:O(n)。计算前缀和需要线性时间,并且在 for 循环的每次迭代中需要恒定时间。因此整体复杂度是O(n)
请注意,上述问题可以使用 Kadane 算法在 O(n) 时间和 O(1) 额外空间内解决

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程