question:
Given an array that has positive and negative numbers, try to find a maximum subarray whose sum is the best.
暴力解法: 复杂度(N^2)
pseudo-code:
FIND-MAXIMUM-SUBARRAY(A, low, high)
- sum = INT_MIN
- for i = low to high - 1
- tmp_sum = A[i]
- for j = i + 1 to high
- tmp_sum = tmp_sum + A[j]
- if tmp_sum > sum
- sum = tmp_sum
- left = i
- right = j
- return (left, right, sum)
typedef struct
{
int low ;
int high ;
int sum ;
} Array_Info;
Array_Info Find_Maximum_Subarray_Force (int A[], int low , int high )
{
Array_Info result ;
int i , j ;
int sum ;
result .sum = INT_MIN ;
for ( i = low; i < high ; i ++)
{
sum = A[ i ];
for ( j = i + 1 ; j <= high ; j ++)
{
sum += A[ j ];
if ( sum > result. sum )
{
result .low = i ;
result .high = j ;
result .sum = sum ;
}
}
}
return result ;
}
// can not to solve the array that all the numbers are negitive
分治法: 复杂度(NlogN)
pseudo-code:
FIND-MAX-CROSSING-SUBARRAY(A, low, mid, high)
- left-sum = INT_MIN
- sum = 0
- for i = mid downto low
- sum = sum + A[i]
- if sum > left-sum
- left-sum = sum
- max-left = i
- right-sum = INT_MIN
- sum = 0
- for j = mind + 1 to high
- sum = sum + A[j]
- if sum > right-sum
- left-sum = sum
- max-right = j
- return(max-left, max-right, left-sum + right-sum)
FIND-MAXIMUM-SUBARRAY(A, low, high)
- if low = high
- return (low, high, A[low])
- else mid = (low + high) / 2
- (left-low, left-high, left-sum) =
- FIND-MAXIMUM-SUBARRAY(A, low, mid)
- (right-low, right-high, right-sum) =
- FIND-MAXIMUM-SUBARRAY(A, mid + 1, high)
- (cross-low, cross-high, cross-sum) =
- FIND-MAX-CROSSING-SUBARRAY(A, low, mid, high)
- if left-sum >= right-sum and left-sum >= cross-sum
- return (left-low, left-high, left-sum)
- elseif right-sum >= left-sum and right-sum >= cross-sum
- return (right-low, right-high, right-sum)
- else return (cross-low, cross-high, cross-sum)
C语言实现:
typedef struct
{
int low ;
int high ;
int sum ;
} Array_Info;
Array_Info Find_Max_Crossing_Subarray (int A[], int low , int mid , int high )
{
int i , j ;
int max_left , max_right ;
int left_sum = INT_MIN ;
int sum = 0 ;
Array_Info cross ;
for ( i = mid; i >= 0 ; i --)
{
sum += A[ i ];
if ( sum > left_sum)
{
left_sum = sum;
max_left = i;
}
}
int right_sum = INT_MIN ;
sum = 0;
for ( j = mid + 1 ; j <= high ; j ++)
{
sum += A[ j ];
if ( sum > right_sum)
{
right_sum = sum;
max_right = j;
}
}
cross .low = max_left ;
cross .high = max_right ;
cross .sum = left_sum + right_sum;
return cross ;
}
Array_Info Find_Maximum_Subarray( int A [], int low, int high )
{
Array_Info base , left , right , cross ;
if ( low == high)
{
base .low = low ;
base .high = high ;
base .sum = A [low ];
return base ;
}
int mid = ( low + high ) / 2;
left = Find_Maximum_Subarray( A , low , mid );
right = Find_Maximum_Subarray( A , mid + 1, high);
cross = Find_Max_Crossing_Subarray (A , low , mid , high );
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 ;
}
线性解法:复杂度(N)
<1>Analyse
从数组左边界开始,从左到右处理,记录到目前为止最大子数组的。若已知A[1....j]的最大子数组,基于如下性质将解扩展为A[1....j + 1]的最大子数组:
A[1....j + 1]的最大子数组为 A[1....j] 的最大子数组或A[i....j + 1] (1 <= i <= j + 1)。
性质分析:
若A[j + 1] >= 0, 并且最大子数组为 A[i....j], 那么A[1....j + 1]最大子数组为A[i....j + 1];
若A[j + 1] >= 0,若最大子数组为A[m....n] (1 <= m < n, n < j),那么 A[1....j + 1]最大子数组为A[1.....j]中最大子数组或A[i....j + 1], A[i...j + 1]满足不存在k (j > k > i)使A[i]+ A[i + 1]..+A[k] < 0
若A[j + 1] < 0, 并且最大子数组为 A[m....n] (1 <=m < n, n <= j),那么A[1...j + 1]中最大子数组为A[m...n];
pseudo-code:
FIND-MAXIMUM-SUBARRAY(A, low, high)
- sum = INT_MIN
- max = INT_MIN
- for i = low to high
- if max < 0
- max = A[i]
- else max = max + A[i]
- if sum < max
- sum = max
- return sum
int Find_Maximum_Subarray ( int A [], int low , int high) { int sum = INT_MIN ; int max = INT_MIN ; for ( int i = low ; i <= high; i++) { if ( max < 0) max = A[ i ]; else max += A[ i ]; if ( sum < max) sum = max; } return sum ; }
备注:
When all the numbers are negative, the function will return the minimun number of the array;