【java笔记】最大连续子列和总结

最近初学编程学习了一个很经典的入门算法题——最大连续子列和问题,为了加深自己的印象,总结了各种解法。

题目:给定一个非空序列,其中可以包括自然数和负数,找出它连续的一个子序列,使子序列的和最大

例:10

       5  7  -6  -8  8  9  5  2  -7  3

其中,10代表序列长度,该序列的最大连续子序列和是22,即第一个数字5累和到第八个数字2。

解法一:暴力法(穷举法)  复杂度O(N^3)

该种解法非常简单直接暴力血腥,我们只需要用两层循环分别枚举序列起点和终点,这样就能得到所有连续子序列,期间不断更新最大子序列的和即可

public static int MaxSubseqSum1(int a[], int n) {
		int ThisSum, MaxSum = 0;
		for (int i = 0; i < n; i++)// i是子列左端的位置
		{
			for (int j = i; j < n; j++)// j是子列右端的位置
			{
				ThisSum = 0;// ThisSum是a[i]到a[j]的子列和
				for (int k = i; k <= j; k++) {
					ThisSum += a[k];
					if (ThisSum > MaxSum)//如果得到的这个子列和更大
						MaxSum = ThisSum;//则更新结果
				}
			}
		}
		return MaxSum;
	}

解法二:暴力法优化  复杂度O(N^2)

分析解法一,发现该算法做了无用功,当j增加1时,没必要从头算起,只需要在i和j的循环之间定义ThisSum=0计算a[i]到a[j]的子列和即可。

public static int MaxSubseqSum2(int a[],int n) {
		int ThisSum,MaxSum=0;
		for(int i=0;i<n;i++) {
			ThisSum=0;
			for(int j=i;j<n;j++) {
				ThisSum+=a[j];
				if(ThisSum>MaxSum)
					MaxSum=ThisSum;
			}
		}
		return MaxSum;
	}

解法三:分治法  复杂度O(NlgN)

解法四:在线处理法  复杂度O(N)

在线处理法,顾名思义就是输入一个数就处理一个数,其大概思想就是一旦前面子序列的和出现了负数,就直接舍去,保证最大子列和递增,代码真的贼鸡儿简单。

例:10  

        5  7  -6  -8  8  9  5  2  -7  3

从第一个元素(5)加到第四个元素(-8)时发现序列和小于0,继续加只会使后面的和加上一个负数而更小,所以应该舍去前四个序列和,再从第五个元素开始,思想就是这个。

public static int MaxSubseqSum4(int a[],int n) {
		int thisSum=0,maxSum=0;
		for(int i=0;i<n;i++) {
			thisSum+=a[i];
			if(thisSum>maxSum)
				maxSum=thisSum;
			else if(thisSum<0)//若此时子列和为负,再继续累加不可能得到最大子列和,必须保证递增
				thisSum=0;
		}
		return maxSum;
	}

解法五:动态规划  复杂度O(N)

有空再分别更新!!!!

猜你喜欢

转载自blog.csdn.net/qq_42370146/article/details/82462450