您的位置:首页 > 其它

最大子串和问题

2014-07-08 22:58 337 查看
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

c语言实现:

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;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: