最大子列和问题

    给定a个整数组成的序列{N_{1},N_{2}...N_{a}},将序列中连续排列的整数构成的新序列定义为连续子列,最大子列和被定义为序列{N_{1},N_{2}...N_{a}}中最大的连续子列。编写一个程序,要求输入一个整数序列,返回它的最大子列和。

算法1:暴力解法

    算法1的思想是引入两个变量ThisSum和MaxSum,前者用来控制连续子列的当前值,后者用来存放连续子列的最大值,对数组内的值从前往后进行依次求和,并且每次求和之后都要对比ThisSum和MaxSum的值,若ThisSum更大,则更新MaxSum的值,每遍历一次数组的各个元素,就扔掉第一个元素(没错,下标为 i 的元素,你已经没有利用价值了),最后返回MaxSum。

 代码如下

//算法1
int MaxSubseqSum1(int A[], int N)
{
	int ThisSum, MaxSum = 0;
	int i, j;
	for (i = 0; i < N; i++)
	{
		ThisSum = 0;
		{
			for (j = i; j < N; j++)
            {
				ThisSum += A[j];
			if (ThisSum > MaxSum)
				MaxSum = ThisSum;
            }
		}
	}
	return MaxSum;
}

//算法1时间复杂度为O(N^2)

算法2:采用递归分而治之

    太复杂了而且有急事,下次写doge,大家可以按照自己的理解将就看看,或者直接快进到算法3,反正算法2的时间复杂度也不是很好。

//算法2,分开用递归求解
int Max(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 List[left];
		else
			return 0;
	}
	//以下是将序列分开的过程
	center = (left + right) / 2;
	MaxLeftSum = DivideAndConquer(List, left, center);
	MaxRightSum = DivideAndConquer(List, center + 1, right);
	//以下是求跨分界线的最大子列和
	MaxLeftBorderSum = 0; LeftBorderSum = 0;
	for (i = center; i >= left; i--)
	{
		LeftBorderSum += List[i];
		if (LeftBorderSum > MaxLeftBorderSum)
			MaxLeftBorderSum = LeftBorderSum;
	}//左边扫描结束
	MaxLeftBorderSum = 0; LeftBorderSum = 0;
	for (i = center + 1; i <= right; i++)
	{
		RightBorderSum += List[i];
		if (RightBorderSum > MaxRightBorderSum)
			MaxRightBorderSum = RightBorderSum;
	}//右边扫描结束
	return Max(MaxLeftSum, MaxRightSum, MaxLeftBorderSum + MaxRightBorderSum);
}
int MaxSubseqSum2(int List[], int N)
{
	return DivideAndConquer(List, 0, N - 1);
}

//算法2时间复杂度为O(NlogN)

 

算法3:动态求解

    与算法1相比,ThisMax用来存放正值,若为负值则直接舍去,随着 i 的增长,会不断更新ThisMax的值(初始化为0或加上下一个值),所以是动态的。以下图为例,第一个值为-5,直接舍去,后面的连续子列的判断也不带上第一个值,第二个值到第四个值的和为-1,也是舍去,在更新ThisMax的过程中与MaxSum进行对比,并保留最大值。

代码如下

//算法3
int MaxSubseqSum3(int A[], int N)
{
	int ThisSum, MaxSum;
	int i;
	ThisSum = MaxSum = 0;
	for (i = 0; i < N; i++)
	{
		ThisSum += A[i];//向右累加
		if (ThisSum > MaxSum)
			MaxSum = ThisSum;
		else if (ThisSum < 0)
			ThisSum = 0;
	}
	return MaxSum;
}

//算法3的时间复杂度为O(N)
  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

毕瞿三谲丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值