给定正负整数数组,找出该数组中的最大子数组总和。
例子:
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. First calculate the prefix sum (prefix_sum) of the input array.
2. Sum of a subarray from index x to y can be presented as,
3. Now maximum of these subarrays is,
That is, we keep track of minimum prefix sum for x <= y and maximum subarray sum so far.
执行:
1.计算输入数组的前缀和。
2.初始化:min_prefix_sum = 0,res = -infinite
3.维持一个从i = 0到n的循环。 (n是输入数组的大小)。
a)cand = prefix_sum [i] –迷你
b)如果cand大于res(到目前为止最大子数组和),则按cand更新res。
c)如果prefix_sum [i]小于min_prefix_sum(到目前为止的最小前缀和),则用prefix_sum [i]更新min_prefix_sum。
4.返回res。
参考: 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前缀总和需要线性时间,并且在for循环的每次迭代中都需要恒定的时间。因此,总体复杂度为O(n) 。
请注意,上述问题可以使用Kadane算法在O(n)时间和O(1)额外空间中解决