题目:输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值以及子数组的起始和终止下标。要求时间复杂度为O(n)。
可采用动态规划的思想,将数组累加值划分成一段一段进行分析,分段规则:累加值小于0时,重新分段;当累加值大于最大值时,更新最大值。
示意图:
代码:
#include <stdio.h>
int max_sub_array(int *array, int len, int *start_idx, int *end_idx, int *max_sum);
int main()
{
int start;
int end;
int sum;
//int a[10]={1, -2, 3, 10, -4, 7, 2, -5};
//int a[] = {3, -23, 30, -20, 40, -60, 55, -35, 45, 5, -80, 50, 5};
int a[] = {-10, -20, -3, -30, -22, -1,-90};
max_sub_array(a, sizeof(a)/sizeof(int), &start, &end, &sum);
printf("start=%d, end=%d, sum=%d, detail=[ ", start, end, sum);
int i;
for (i=start; i<=end; i++)
printf("%d ", a[i]);
printf("]\n");
return 0;
}
//动态规划思想,划分为一段一段处理。
int max_sub_array(int *array, int len, int *start_idx, int *end_idx, int *max_sum)
{
int sum = 0;
int idx = 0;
int i;
*max_sum = 0;
*start_idx = 0;
for (i=0; i<len; i++)
{
sum += array[i];
if (sum < 0)//划分为新阶段
{
sum = 0;
idx = i;
}
if (sum > *max_sum)//更新最大值
{
*max_sum = sum;
*start_idx = idx + 1;
*end_idx = i;
}
}
if (*max_sum == 0)//全部元素都小于0
{
*max_sum = array[0];
*start_idx = 0;
for (i=1; i<len; i++)
{
if (array[i] > *max_sum)
{
*max_sum = array[i];
*start_idx = i;
*end_idx = i;
}
}
}
return *max_sum;
}