给定的数组,元素可能为正或者为负
方法 1. broute-force
这个是最容易想到的方法,就是把每个可能的子数组列出来,计算出元素之和,然后把最大的挑出来。显然,这个算法的时间复杂度为 O(n^2)
struct tuple FindMaxSubArray(int *array, int size)
{
struct tuple t;
t.sum = INT_MIN;
int i, j;
for(i = 0; i < size; i++)
{
int sum = 0;
for( j = i; j < size; j++)
{
sum += array[j];
if(sum > t.sum)
{
t.sum = sum;
t.start = i;
t.end = j;
}
}
}
return t;
}
struct tuple
{
int start, end;
int sum;
};
方法2: divide-and-conquer
把一个数组分成两个,使用递归的方法。时间复杂度是 O(nlgn)
struct tuple FindMaxCrossSubArray(int *array, int start, int mid, int end)
{
int i;
struct tuple left;
left.sum = INT_MIN;
int sum = 0;
for(i = mid; i >= start; i--)
{
sum += array[i];
if(sum > left.sum)
{
left.start = i;
left.end = mid;
left.sum = sum;
}
}
sum = 0;
struct tuple right;
right.sum = INT_MIN;
for(i = mid + 1; i <= end; i++)
{
sum += array[i];
if(sum > right.sum)
{
right.start = mid + 1;
right.end = i;
right.sum = sum;
}
}
struct tuple combined = {left.start, right.end, left.sum + right.sum};
return combined;
}
struct tuple FindMaxSubArray2(int *array, int start, int end)
{
struct tuple t;
if(start == end)
{
t.start = start;
t.end = end;
t.sum = array[start];
return t;
}
else
{
int mid = (start + end) / 2;
struct tuple left, right, cross;
left = FindMaxSubArray2(array, start, mid);
right = FindMaxSubArray2(array, mid + 1, end);
cross = FindMaxCrossSubArray(array, start, mid, end);
if(left.sum >= right.sum && left.sum >= cross.sum)
{
return left;
}
else if(right.sum >= left.sum && right.sum >= cross.sum)
{
return right;
}
else
{
return cross;
}
}
}
3. 通过分析数组 array[i]的最大子数组来确定 array[i+1]的最大子数组。这种方法的时间复杂度可以降低到 O(n).
struct tuple find_maximum_subarray4(int *array, unsigned left, unsigned right)
{
struct tuple suffixes[right - left + 1];
int i;
suffixes[0].start = left;
suffixes[0].end = left;
suffixes[0].sum = array[left];
for (i = left + 1; i <= right; i++) {
if (suffixes[i - 1].sum < 0) {
suffixes[i].start = i;
suffixes[i].end = i;
suffixes[i].sum = array[i];
} else {
struct tuple *previous = &suffixes[i - 1];
suffixes[i].start = previous->start;
suffixes[i].end = i;
suffixes[i].sum = previous->sum + array[i];
}
}
struct tuple *max = &suffixes[0];
for (i = left + 1; i <= right; i++) {
if (max->sum < suffixes[i].sum) {
max = &suffixes[i];
}
}
return *max;
}
对一个大小为10万的随机数组进行测试,
三种算法花费的时间分别为:
ime spent: 14.598223 seconds
time spent: 0.007730 seconds
time spent: 0.001730 seconds