最大连续子序列和

原创 2018年04月16日 16:32:27

什么是最大连续子序列和问题?

问题描述:给定一个序列(整数或浮点数),求出其中连续的子序列和最大的那一个。

例:序列{-10 1 2 3 4 -5 -23 3 7 -21},其最大的连续子序列为{1 2 3 4}或{3 7},最大和为10.

方法一:暴力求解

最最普通的方法,效率十分低,一般不会用到,这里简单介绍。直接两个for循环枚举子序列的首尾,再来一个for循环计算首尾之间的序列和,计算所有的序列和,找到最大值。

时间复杂度:O(n^3)

效率贼低,千万不要用!(所就不贴代码了)

 

方法二:预处理暴力求解

第一种方法为什么这么慢,原因之一是每次都要计算首尾之间的序列和。基于这个考虑,我们可以对数据进行预先处理:读入数据时使用一个数组SUM[i]来记录前i项数据之和。用这种方法,只需要两个for循环枚举子序列的首尾,利用SUM数组计算子序列和,找到最大值。

时间复杂度:O(n^2)

剩下两种分别是分治法和动态规划方法,在一个具体的问题中实现这两种算法。

题目:

1007. Maximum Subsequence Sum (25)

时间限制
400 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Given a sequence of K integers { N1, N2, ..., NK }. A continuous subsequence is defined to be { Ni, Ni+1, ..., Nj } where 1 <= i <= j <= K. The Maximum Subsequence is the continuous subsequence which has the largest sum of its elements. For example, given sequence { -2, 11, -4, 13, -5, -2 }, its maximum subsequence is { 11, -4, 13 } with the largest sum being 20.

Now you are supposed to find the largest sum, together with the first and the last numbers of the maximum subsequence.

Input Specification:

Each input file contains one test case. Each case occupies two lines. The first line contains a positive integer K (<= 10000). The second line contains K numbers, separated by a space.

Output Specification:

For each test case, output in one line the largest sum, together with the first and the last numbers of the maximum subsequence. The numbers must be separated by one space, but there must be no extra space at the end of a line. In case that the maximum subsequence is not unique, output the one with the smallest indices i and j (as shown by the sample case). If all the K numbers are negative, then its maximum sum is defined to be 0, and you are supposed to output the first and the last numbers of the whole sequence.

Sample Input:
10
-10 1 2 3 4 -5 -23 3 7 -21
Sample Output:
10 1 4

方法三:分治法求解

把序列分成左右两部分,一般对半分,数量不等也没关系。最大子序列和的位置存在三种情况:1、完全在左半部分;2、完全在右半部分;3、跨越左右两部分。分别求出左半部分的最大子序列和、右半部分的最大子序列和、以及跨越左右两部分的最大子序列和,三者中的最大者就是要求的。

如何求三部分的最大子序列和呢?

左半部分的最大子序列和,可把左半部分作为新的输入序列通过该算法递归求出。右半部分的最大子序列和同理。

接下来就是求解跨越左右两部分的最大子序列和,也就是求出包含左半部分中最右边元素的子序列的最大和,和包含右半部分中最左边元素的子序列的最大和,将两者相加即为跨越左右两个部分的最大子序列和。具体见如下代码:

//分治算法 
int a[999999];

int MAxSubSum(int left,int right)
{
    int sum=0;
    if(left==right)//基本情况:只有一个元素 
        sum=a[left]>0?a[left]:0;
    else
    {
        int center=(left+right)/2;
        int leftsum=MaxSubSum(left,center);//左半部分 
        int rightsum=MAxSubSum(center+1,right);//右半部分 
        
        //求包含左半部分最右元素的最大和 
        int s1=0;
        int lefts=0;
        for(int i=center;i>=left;i--)
        {
            lefts+=a[i];
            if(lefts>s1) s1=lefts;
        }
        
        //求包含右半部分最左元素的最大和 
        int s2=0;
        int rights=0;
        for(int i=center+;i<=right;i++)
        {
            rights+=a[i];
            if(rights>s2) s2=rights;
        }
        
        //取三者最大值 
        sum=s1+s2;
        if(sum<leftsum) sum=leftsum;
        if(sum<rightsum) sum=rightsum;
    }
    return sum;
}

方法四:动态规划

具体算法:

状态转移方程:sum[i] = max{sum[i-1]+a[i],a[i]}. (sum[i]记录以a[i]为子序列末端的最大序子列连续和)

//动态规划算法
int MaxSum(int n)
{
    int sum=0,b=0;
    for(int i=0;i<n;i++)
    {
        if(b>0) b+=a[i];
        else b=a[i];
        if(b>sum) sum=b;
    }
    return sum;
}
题目代码:
#include <stdlib.h> 
#include <stdio.h>
int main() 
{
	int k,i;
	int ThisSum=0,MaxSum;	//当前子列和,最大子列和
	int first,tempfirst,last,templast;
	scanf("%d",&k);
	int a[k];
	
	for(i=0;i<k;i++)
	{
		scanf("%d",&a[i]);
	}
	MaxSum=a[0];	//初始化数值
	tempfirst=a[0];
	templast=a[0];
	first=a[0];
	last=a[0];
	for(i=0;i<k;i++)
	{
		if(ThisSum>=0)	//当前子列和大于或等于0时,templast移动到当前元素,且当前子列和累加该元素

		{
			ThisSum+=a[i];	
			templast=a[i];
		}else{	//当前子列和小于0时,当前元素作为新的子列和,templast和tempfirst均为当前元素

			ThisSum=a[i];
			tempfirst=a[i];
			templast=a[i];
		}
		if(ThisSum>MaxSum)	//当前子列和大于最大子列和时,存储和、起始元素
		{
			MaxSum=ThisSum;
			last=templast;
			first=tempfirst;
		}
	}
	if(MaxSum<0)	//当最大子列和小于0,即所有元素都是负数,最大子列和为0,存储起始的元素
		{
			MaxSum=0;
			last=a[k-1];
			first=a[0];	
		}
	printf("%d %d %d\n",MaxSum,first,last);
	return 0;
} 


版权声明: https://blog.csdn.net/bxg1065283526/article/details/79962501

最大连续子序列和:递归和动态规划

问题描述: 给定一个整数序列,a0, a1, a2, …… , an(项可以为负数),求其中最大的子序列和。如果所有整数都是负数,那么最大子序列和为0; 方法一: 用了三层循环,因为要找到这个子序列...
  • anlian523
  • anlian523
  • 2017-07-17 15:21:05
  • 2914

HDU1231:最大连续子序列

Problem Description 给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ...,  Nj },其中 1 例如给定序...
  • libin56842
  • libin56842
  • 2013-08-26 10:54:08
  • 5134

六种姿势拿下连续子序列最大和问题,附伪代码(以HDU 1003 1231为例)

问题描述:       连续子序列最大和,其实就是求一个序列中连续的子序列中元素和最大的那个。       比如例如给定序列:            { -2, 11, -4, 13, -5, -2...
  • hcbbt
  • hcbbt
  • 2013-08-28 21:13:53
  • 17566

最大连续子序列和:动态规划经典题目(2)

问题描述:       连续子序列最大和,其实就是求一个序列中连续的子序列中元素和最大的那个。       比如例如给定序列:            { -2, 11, -4, 13, -5,...
  • samjustin1
  • samjustin1
  • 2016-07-27 10:47:01
  • 6156

HDU 1231 最大连续子序列——最大连续和+输出其起始点

题意:求一个序列的最大连续和 思路:普通的求最大连续和算法,但是起始点的更新要特别注意,首先起始点的更新一定是在更新最大连续和ans的时候更新,但是在sum 还有就是一般的写法可能不能兼顾题目中...
  • hao_zong_yin
  • hao_zong_yin
  • 2017-08-10 10:26:11
  • 151

hdu 1003 Max Sum(最大连续子序列和) (学了一下分治)

都不知道以前刷杭电是怎么做的最大连续子序列和,
  • u012659423
  • u012659423
  • 2014-07-17 13:03:47
  • 1303

最大连续子序列和(java)

最大连续子序列是算法中经典的一个问题。作为总结,今天就从最简单的暴力求解,写道目前能达到最好的线性时间复杂度的算法。 问题描述:找出一个整型数组中的最大连续子序列的和 测试用例:int[] a =...
  • jiaohanhan
  • jiaohanhan
  • 2017-05-13 14:31:46
  • 1204

HDU最大连续子序列

动态规划
  • wyxeainn
  • wyxeainn
  • 2016-09-06 19:28:58
  • 322

leetcode | Maximum Subarray 最大连续子序列的和

Maximum Subarray: https://leetcode.com/problems/maximum-subarray/ Find the contiguous subarray with...
  • quzhongxin
  • quzhongxin
  • 2015-06-23 11:27:52
  • 1617
收藏助手
不良信息举报
您举报文章:最大连续子序列和
举报原因:
原因补充:

(最多只允许输入30个字)