《数据结构与算法》(浙大MOOC)1.4最大子列和

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值