1.4 解决最大子列和问题的收获
- 同一问题的不同算法可以带来时间和空间上的改进
通常当算法的复杂度为O(n^2)时可以改进为O(nlogn)。
- C语言中的三目运算符的应用
return A>C?(A>B?A:B):(C>B?C:B);/*三目运算符的应用*/
- 递归求算法的时间复杂度和空间复杂度
- 算法的空间复杂度的具体求法(未解决)
理由:几乎没有计算过空间复杂度,初步观察和时间复杂度差不多。
/*2020/7/12
输入:
8
4 -3 5 -2 -1 2 6 -2
*/
#include<stdio.h>
void MaxSubseqSum1(int list[], int N);//算法一:T(f)=O(n^2)
void MaxSubseqSum2(int list[], int N);//算法二:T(f)=O(nlogn)
void MaxSubseqSum3(int list[], int N);//算法三:T(f)=O(n)
int Max3(int A,int B,int C);//返回三个数中的较大数
int DivideAndConquer(int list[], int left, int right);//分治算法
int main()
{
int n,num[1000000];
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&num[i]);
MaxSubseqSum1(num,n);
MaxSubseqSum2(num,n);
MaxSubseqSum3(num,n);
return 0;
}
void MaxSubseqSum1(int list[], int N)
{
int i=0,j=0,k=0,sum=0,thisSum=0;
int left=list[0],right;
for(i=0;i<N;i++)
{
thisSum=list[i];
for(j=i+1;j<N;j++)
{
thisSum+=list[j];
if(thisSum>sum)
{
sum=thisSum;
left=list[i];
right=list[j];
}
}
thisSum=0;
}
printf("Algorithm1:\n");
printf("left:%d right;%d sum:%d\n",left,right,sum);
return;
}
int Max3(int A,int B,int C)
{/* 返回三个整数的最大值*/
return A>B?(A>C?A:C):(B>C?B:C);
}
int DivideAndConquer(int list[],int left,int right)
{
int MaxLeftSum,MaxRightSum;/*存放左右子问题的解*/
int MaxLeftBorderSum,MaxRightBorderSum;/*存放跨分界线的结果*/
int LeftBorderSum,RightBorderSum;
int center,i;
if(left==right)/*递归的终止条件,子列只有一个数字*/
{
if(list[left]<0) return 0;
else return list[center];
}
/*下面是“分”的过程*/
center=(left+right)/2;/*找到中分点*/
/*递归的一个分支,找子列左端的最大值*/
MaxLeftSum=DivideAndConquer(list,left,center);
/*递归的第二个分支,找到子列右边的最大值*/
MaxRightSum=DivideAndConquer(list,center+1,right);
/*递归的第三个分支,找到子列边界左端的最大值*/
LeftBorderSum=0;
MaxLeftBorderSum=list[center];
for(i=center;i>=left;i--)/*从中线向左扫描*/
{
LeftBorderSum+=list[i];
if(LeftBorderSum>MaxLeftBorderSum)
MaxLeftBorderSum=LeftBorderSum;
}/*左边扫描结束*/
/*递归的第四个分支,找到子列边界右端的最大值*/
RightBorderSum=0;
MaxRightBorderSum=list[center+1];
for(i=center+1;i<=right;i++)/*从中间向右扫描*/
{
RightBorderSum+=list[i];
if(RightBorderSum>MaxRightBorderSum)
MaxRightBorderSum=RightBorderSum;
} /*右边扫描结束*/
/*下面返回“治”的结果*/
return Max3(MaxLeftBorderSum+MaxRightBorderSum,MaxLeftSum,MaxRightSum);
}
void MaxSubseqSum2(int list[], int N)
{
int maxSum;
maxSum=DivideAndConquer(list,0,N-1);
printf("Algorithm2:\n");
printf("%d\n",maxSum);
return;
}
void MaxSubseqSum3(int list[],int N)
{
int maxSum=0,thisSum=0;
int left1=list[0],left=list[0],right=list[0];
for(int i=0;i<N;i++)
{
thisSum+=list[i];/*向右累加*/
if(thisSum>maxSum)
{
left=left1;
right=list[i];
maxSum=thisSum;/*如果发现更大则更新当前结果*/
}
else if(thisSum<0)
{
thisSum=0;/*如果当前子列和为负,抛弃之*/
left1=list[i+1];
}
}
printf("Algorithm3:\n");
printf("left:%d right:%d sum:%d",left,right,maxSum);
return;
}