点击(此处)折叠或打开
-
总感觉求最小子序列乘积有些问题,请高手证明下正确性
-
-
/*
-
*最小子序列和
-
*最大子序列乘积
-
*最小子序列乘积
-
*/
-
-
#include<stdio.h>
-
-
#define MAX2(A,B) ( (A>B)?A:B )
-
#define MIN2(A,B) ( (A>B)?B:A )
-
-
int min_sub_sum(int A[],int N);
-
int max_sub_multi(int A[],int left,int right);
-
-
int min_sub_multi(int A[],int left,int right);
-
-
-
int main(void)
-
{
-
int A[] = {4,0,0,3};
-
-
for(int i = 0; i < sizeof(A)/sizeof(int);++i)
-
printf("%d ",A[i]);
-
putchar('\n');
-
-
printf("最小子序列和为:%d\n", min_sub_sum(A,sizeof(A)/sizeof(int)) );
-
printf("最大子序列乘积为:%d\n", max_sub_multi(A,0,sizeof(A)/sizeof(int)-1) );
-
printf("最小子序列乘积为:%d\n", min_sub_multi(A,0,sizeof(A)/sizeof(int)-1) );
-
-
return 0;
-
}
-
-
//o(N):最小子序列的和,如果最小子序列和为正数,那么返回最小的正数
-
int min_sub_sum(int A[],int N)
-
{
-
int i,min_sum,cur_sum;
-
int j;
-
min_sum = cur_sum = 0;
-
j = 0;
-
-
for(i = 0;i < N; ++i)
-
{
-
if(A[i] >= 0)
-
j++;
-
cur_sum += A[i];
-
if(cur_sum < min_sum)
-
min_sum = cur_sum;
-
else if(cur_sum > min_sum)
-
cur_sum = 0;
-
}
-
-
if(j == N)
-
{
-
min_sum = A[0];
-
for(i = 1; i < N; ++i)
-
{
-
if(A[i] < min_sum)
-
min_sum = A[i];
-
}
-
}
-
-
return min_sum;
-
}
-
-
//o(N*logN) 最大子序列乘积
-
int max_sub_multi(int A[],int left,int right)
-
{
-
int left_max,right_max,max_from_pos,max_from_neg;
-
int left_max_pos,right_max_pos,left_min_neg,right_min_neg;
-
int multi;
-
int i,center;
-
-
if(left == right)
-
return A[left];
-
-
center = (left+right) / 2;
-
-
left_max = max_sub_multi(A,left,center);
-
right_max = max_sub_multi(A,center+1,right);
-
-
//分界处扩至最左边序列乘积最大正值或者最小负值
-
left_max_pos = left_min_neg = 0;
-
multi = 1;
-
for(i = center;i >= left; --i)
-
{
-
multi *= A[i];
-
if(multi > 0 && multi > left_max_pos)
-
left_max_pos = multi;
-
if(multi < 0 && multi < left_min_neg)
-
left_min_neg = multi;
-
}
-
-
//分界处扩至最右边序列最大正值或者最小负值
-
right_max_pos = right_min_neg = 0;
-
multi = 1;
-
for(i = center+1 ; i <= right ; ++i)
-
{
-
multi *= A[i];
-
if(multi > 0 && multi > right_max_pos)
-
right_max_pos = multi;
-
if(multi < 0 && multi < right_min_neg)
-
right_min_neg = multi;
-
}
-
-
max_from_pos = left_max_pos*right_max_pos;
-
max_from_neg = left_min_neg*right_min_neg;
-
-
//找出最大值
-
return MAX2( MAX2(left_max,right_max) , MAX2(max_from_pos,max_from_neg) );
-
}
-
-
-
//o(N*logN) 最小子序列乘积
-
int min_sub_multi(int A[],int left,int right)
-
{
-
int left_min,right_min,min_from_pos,min_from_neg;
-
int left_max_pos,right_max_pos,left_min_neg,right_min_neg;
-
int multi;
-
int i,center;
-
-
if(left == right)
-
return A[left];
-
-
center = (left+right) / 2;
-
-
left_min = min_sub_multi(A,left,center);
-
right_min = min_sub_multi(A,center+1,right);
-
-
//分界处扩至最左边序列乘积最大正值或者最小负值
-
left_max_pos = left_min_neg = 0;
-
multi = 1;
-
for(i = center;i >= left; --i)
-
{
-
multi *= A[i];
-
if(multi > 0 && multi > left_max_pos)
-
left_max_pos = multi;
-
if(multi < 0 && multi < left_min_neg)
-
left_min_neg = multi;
-
}
-
-
//分界处扩至最右边序列最大正值或者最小负值
-
right_max_pos = right_min_neg = 0;
-
multi = 1;
-
for(i = center+1 ; i <= right ; ++i)
-
{
-
multi *= A[i];
-
if(multi > 0 && multi > right_max_pos)
-
right_max_pos = multi;
-
if(multi < 0 && multi < right_min_neg)
-
right_min_neg = multi;
-
}
-
-
//处理最小子序列乘积大于0时情况
-
if(left_min_neg == 0 && right_min_neg == 0)
-
return MIN2( MIN2(left_min,right_min) , MIN2(left_max_pos,right_max_pos) );
-
-
min_from_pos = left_max_pos*right_min_neg;
-
min_from_neg = left_min_neg*right_max_pos;
-
return MIN2( MIN2(left_min,right_min) , MIN2(min_from_pos,min_from_neg) );
- }