子序列求和问题

问题描述:给定一整数序列A1,A2,...,An(可含负数),求A1-An中的一个子序列Ai-Aj,使得Ai-Aj的和最大,求该和的值。

涉及变量:sequence:int[]型常量,给定整数序列

n:实际元素个数

sum:int型变量,子序列之和

max:int型变量,最大子序列之和

i:int型变量,下标

涉及教材:《数据结构——Java语言描述(第2版)》 清华大学出版社

第一次看到这道题时我的思路是用三个for循环解决问题:

1.将max的初值赋为sequence[0]

2.从下标为0,1,..,n-1的位置开始计算每一个子序列的和并存放在sum变量中

3.比较sum与max,若sum>max,则将max赋值为sum所存储值,否则不变

4.结束for循环后,返回max

这种简单粗暴的方法,原理简单,但没有太多技巧,说白了就是全部算一遍,费时费力。其时间复杂度为O(n^3),当序列较大时不适合使用这种方法

第二次看到这道题是在教科书上,书上介绍了4种关于该问题的求解方式,包括上面我第一次想到的思路且有其改良版,但此处只讲我最喜欢的一种算法的思路:

1.将max和sum都赋初值为0

2.当i<sequence.length,for循环中执行每一个数加到sum中

3.若sum>max,则将max赋值为sum

4.若sum<0,将sum清空为0重新开始计算

5.结束for循环后,返回max

第4步操作是因为若前面的子序列之和小于0,则必定会影响后面正整数子序列之和,使其无法达到最大子序列之和,故将其赋值为0,表示从这一元素开始重新计算子序列之和

书上代码如下:

第4步十分巧妙地避免了重算子序列的麻烦,但同时由于这一步,这个算法对整个序列都为负数时无能为力

为了能解决全负数的序列求和问题,我改良了这个算法

我的思路:

1.将max赋值为sequence[0],sum赋值为0

2.用for语句开始执行子序列最大求和的运算和对比,循环结束条件为对数组各元素的一次遍历结束后

3.每次执行sum+=sequence[i],即求子序列之和

4.若sum>max时,有两种可能

(1)sequence[i]比sum大,sum由于前面存在的负数而影响了sum的最大可能,此时将max赋值为sum

(2)其他情况,sum>=sequence[i],将max赋值为sum

5.当sum小于0时,会对最大子序列之和造成影响,故将sum清零重新计算

//这一步可能有人会奇怪4和5似乎相互矛盾了,上一步当sum<0时不是已经被清零了吗,下一次怎么又会在第一个if里出现小于0的情况,这里是考虑到了全负数序列的情况

假设所给出序列为 {-6,-2,-1},

第1次循环时max=-6,sum=-6,不符合if执行条件,进入else if,sum=0,i=1

第2次循环时max=-6,sum=-2,符合sum>max的if执行条件,且执行else语句,得max=-2,sum=0,i=2

第3次循环时max=-2,sum=-1,符合sum>max的if执行条件,其符合里面的if(sequence[i]>sum)的执行条件,得max=-1,sum=0,i=3,结束循环

以下为代码:

代码本身的for循环其实可以用do_while循环替代,思路大体不变

以上是我关于子序列求和的部分思考和代码,希望对各位有所帮助

190111  Rewivy

原文地址:https://www.cnblogs.com/rewivy/p/10255723.html

时间: 2024-10-12 17:28:34

子序列求和问题的相关文章

转~最大连续子序列求和

最大连续子序列求和详解 1.        问题描述 输入一个整数序列(浮点数序列也适合本处讲的算法),求出其中连续子序列求和的最大值. 2.        算法分析 2.1.        算法一 2.1.1.       算法描述 遍历所有子序列并求和,比较得出其中的最大值. 2.1.2.       代码描述 1          public static int maxSubSumCubic(int[] array) { 2                 int maxSum = 0

最大连续子序列求和详解

最大连续子序列求和详解 1.        问题描述 输入一个整数序列(浮点数序列也适合本处讲的算法),求出其中连续子序列求和的最大值. 2.        算法分析 2.1.        算法一 2.1.1.       算法描述 遍历所有子序列并求和,比较得出其中的最大值. 2.1.2.       代码描述 1          public static int maxSubSumCubic(int[] array) { 2                 int maxSum = 0

[C++]四种方式求解最大子序列求和问题

问题 给定整数: A1,A2,-,An,求∑jk=iAk 的最大值(为方便起见,假设全部的整数均为负数,则最大子序列和为0) 比如 对于输入:-2,11,-4,13,-5,-2,答案为20,即从A2到A4 分析 这个问题之所以有意思.是由于存在非常多求解它的算法. 解法一:穷举遍历 老老实实的穷举出全部的可能,代码例如以下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 //计算并返回所

最大子序列求和算法二三

最大子序列求和算法二 递归求解 递归求解:整个求解数组分成三部分,最大子序列可能出现在三个地方,左半部分,右半部分,跨越左右部分(包括左半部分最后一个元素,右半部分第一个元素) 分别对这三部分求解,不断的在每部分再分成三部分,递归求解 每一次递归跨越部分可以先算出,但是左,右半部分,需要不断递归,知道剩一个元素,然后回溯加上原来已经算出的跨越部分,最后返回max3(三个里面最大的一个) 时间复杂度计算 假设递归求解需要时间为T(N) ,N=1 时 T(1)=1 两个递归时间+两个for循环时间(

snnu1111(子序列求和)

1111: 子序列求和 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 10  Solved: 2[Submit][Status][Web Board] [Edit] Description 给出n个数字,分别为1,2,3,……,n.从中选出t个数字,且这t个数字和为x的方案数为ft,x .给出m.输出下面的值: 数据满足n <= 20000,m <= min(10, n). Input 第一行输入T表示测试数据的行数.接下来T行,每行两个数字n,

力扣152,53题,最大子序列求和and积

本内容为最大子序列的求和和求积.采用DP的思路, 当前值加上小于之前值,则从该节点重新算起. 这个代码只能返回其结果值,但不能返回最后的子序列(待修改). class Solution: def maxSubArray(self,arr): #最大子数组和的DP求解 if not arr:return cur_sub,max_sub = arr[0],arr[0] #记录当前集合和最大集合 res = [arr[0]] for i in range(1,len(arr)): #从第二个开始遍历

ZOJ 3872 Beauty of Array 连续子序列求和

Edward has an array A with N integers. He defines the beauty of an array as the summation of all distinct integers in the array. Now Edward wants to know the summation of the beauty of all contiguous subarray of the array A. Input There are multiple

最大子序列求和问题

题目: 给定K个整数组成的序列{ N1, N2, ..., NK },“连续子列”被定义为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= K.“最大子列和”则被定义为所有连续子列元素的和中最大者.例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20.现要求你编写程序,计算给定整数序列的最大子列和. 输入格式: 输入第1行给出正整数 K (<= 100000):第2行给出K个整数,其间以

最大子序列求和模版

long max3(long a, long b, long c) { if (a < b) a = b; if (a > c) return a; else return c; } long maxSumRec(const vector<int>& a, int left, int right) { if (left == right) { if (a[left] > 0) return a[left]; else return 0; } int center =