最大连续区间和的算法总结(转)

最大连续区间和是一个经典的问题。给定一个长度为n的序列a[1],a[2]...a[n-1],a[n],求一个连续的子序列a[i],a[i+1]...a[j-1],a[j],使得a[i]+a[i+1]...a[j-1]+a[j]最大。

①最简单最容易想到的就是根据定义来枚举。
枚举上下界{i,j | 0<=i<=j<=n},维护一个max值即可。
其中枚举上下界的时间复杂度为O(n^2),求区间和的复杂度为O(n),所以总时间复杂度为O(n^3)。

for ( int i = 1 ; i <= n ; i++ )
    for ( int j = i ; j <= n ; j++ )
        ans = max(ans,accumulate(a+i,a+j+1,0));

②其实就是第一种方法的优化。
这里有个很容易想到的优化,即预处理出前缀和sum[i]=a[0]+a[1]+...+a[i-1]+a[i],算区间和的时候即可将求区间和的复杂度降到O(1),枚举上下界的复杂度不变,所以总时间复杂度为O(n^2)。

for ( int i = 1 ; i <= n ; i++ )
    sum[i]=sum[i-1]+a[i];
for ( int i = 1 ; i <= n ; i++ )
    for ( int j = i ; j <= n ; j++ )
        ans = max(ans,sum[j]-sum[i-1]);

③可以利用动态规划的思维来继续优化,得到一个线性的算法,也是最大连续区间和的标准算法
定义maxn[i]为以i为结尾的最大连续和,则很容易找到递推关系:maxn[i]=max{0,maxn[i-1]}+a[i]。
所以只需要扫描一遍即可,总时间复杂度为O(n)。

for ( int i = 1 ; i <= n ; i++ )
{
    last = max(0,last)+a[i];
    ans = max(ans,last);
}

④同样用到类似的思维。
首先也需要预处理出前缀和sum[i],可以推出ans=max{sum[i]-min{sum[j] } | 0<=j<i<=n }。
而最小前缀和可以动态维护,所以总时间复杂度为O(n)。

for ( int i = 1 ; i <= n ; i++ )
    sum[i]=sum[i-1]+a[i];
for ( int i = 1 ; i <= n ; i++ )
{
    ans = max(ans,sum[i]-minn);
    minn = min(minn,sum[i]);
}

总结:虽然朴素的O(n^3)和前缀和优化的O(n^2)算法很容易想到,但代码实现却反而比方法三麻烦,第四个方法虽然有和方法三相同的复杂度,但需要一个预处理和多出的O(n)的空间,所以,方法三很好很强大。

时间: 2024-08-01 06:41:19

最大连续区间和的算法总结(转)的相关文章

最大连续区间和的算法总结

最大连续区间和是一个经典的问题.给定一个长度为n的序列a[1],a[2]...a[n-1],a[n],求一个连续的子序列a[i],a[i+1]...a[j-1],a[j],使得a[i]+a[i+1]...a[j-1]+a[j]最大. ①最简单最容易想到的就是根据定义来枚举.枚举上下界{i,j | 0<=i<=j<=n},维护一个max值即可.其中枚举上下界的时间复杂度为O(n^2),求区间和的复杂度为O(n),所以总时间复杂度为O(n^3). (  i = 1 ; i <= n ;

最大连续区间和问题

2017-08-27 16:38:47 writer:pprp 最大连续区间和,可以有很多种方法实现,其中最常见的是运用一维前缀和还有动态规划来解决的: 代码如下: /* @theme:最大连续区间和的算法 @writer:pprp @declare:有几种方法 @date:2017/8/27 */ #include <bits/stdc++.h> using namespace std; const int maxn = 10000; int a[maxn]; int sum[maxn];

二分算法~~~大综合

二分:一个非常神奇的算法:永远记住二分,分的是答案,直接在答案在的区间范围中二分,分出一个值,就判断是不是           答案,并进行转移 二分答案: 如果已知候选答案的范围[min,max],有时候我们不必通过计算得到答案,只需在此范围内应用“二分”的过程,逐渐靠近答案(最后,得到答案)! 一.何时可以使用“二分答案” 不是任何题目都适合使用“二分答案”的,我Sam观察到一般有以下的一些特征: A. 候选答案必须是离散的 ,且已知答案的范围是:[最小值min, 最大值max] (连续区间

致佳音: 推箱子游戏自动求解算法设计(三)

这一节我们说说闭合曲线的填充,为什么会有这个东西呢 当我们递归一个场景时,我们以推动箱子为标志,如果不推动箱子,那么跑到哪里都白跑,而出现重复的判别最好就是所有坐标相同 包括这些坐标互换位置(排序结果相同),而后一个场景搬运工坐标能移动到另一个场景搬运工的位置(求解算法部分再详细说) 由于场景有多个箱子,每个箱子可以有几个方向移动,反复的寻路效率不高,起初我想删除路径部分,只检测能否移动到目标 来提升执行效率,就是偷懒一下,然后想想既然是礼物,偷懒也不是分时候,也有脸献给别人于是废弃了A×算法

图像特征提取:SIFT定位算法关键步骤的说明

1. SIFT算法中一些符号的说明 $I(x,y)$表示原图像. $G(x,y,\sigma)$表示高斯滤波器,其中$G(x,y,\sigma) = \frac{1}{2\pi\sigma^2}exp(-(x^2+y^2)/2\sigma^2)$. $L(x,y,\sigma)$表示由一个高斯滤波器与原图像卷积而生成的图像,即$L(x,y,\sigma) = G(x,y,\sigma)\otimes I(x,y)$.一系列的$\sigma_i$,则可以生成一系列的$L(x,y,\sigma_i)

具体解释Redis源代码中的部分高速排序算法(pqsort.c)

看标题.你可能会疑惑:咦?你这家伙.怎么不解说完整的快排,仅仅讲一部分快排---.- 哎,冤枉. "部分快排"是算法的名字.实际上本文相当具体呢.本文差点儿与普通快排无异.看懂了本文,你对普通的快排也会有更深的认识了. 高速排序算法(qsort)的原理我们大都应该了解.本文介绍的是部分高速排序算法. 事实上其算法本质是一样的,仅仅只是限定了排序的左右区间.也就是仅仅对一个数字序列的一部分进行排序.故称为"部分高速排序算法".简称:pqsort Redis项目中的pq

算法系列之二十四:离散傅立叶变换之音频播放与均衡器

导语 在算法系列的第二十二篇,我们介绍了离散傅立叶变换算法的实现,将时域的音频信号转换到频域进行分析,获取拨号音频的频率特征.这一篇我们将介绍一种频域均衡器的实现方法,所谓的频域均衡器,就是在频域信号的基础上对音频数据进行调整,然后再将频域信号转换成时域信号在回放设备上播放,从而达到音色调节的目的.将频域信号转换成时域信号的算法,就是离散傅立叶逆变换算法. 1 离散傅立叶逆变换 有从时域转换到频域的方法,就必然有从频域转换到时域的方法,相对于离散傅里叶变换,这个反向转换就是离散傅里叶逆变换(ID

详解Redis源码中的部分快速排序算法(pqsort.c)

看标题,你可能会疑惑:咦?你这家伙,怎么不讲解完整的快排,只讲一部分快排---.- 哎,冤枉."部分快排"是算法的名字,实际上本文相当详细呢.本文几乎与普通快排无异.看懂了本文,你对普通的快排也会有更深的认识了. 快速排序算法(qsort)的原理我们大都应该了解.本文介绍的是部分快速排序算法.其实其算法本质是一样的,只不过限定了排序的左右区间,也就是只对一个数字序列的一部分进行排序,故称为"部分快速排序算法",简称:pqsort Redis项目中的pqsort.c

树状数组详解(图形学算法)

目录 一.从图形学算法说起 1.Median Filter 概述 2.r pixel-Median Filter 算法 3.一维模型 4.数据结构的设计 5.树状数组华丽登场 二.细说树状数组 1.树 or 数组? 2.结点的含义 3.求和操作 4.更新操作 5.lowbit函数O(1)实现 6.小结 三.树状数组的经典模型 1.PUIQ模型 2.IUPQ模型 3.逆序模型 4.二分模型 5.再说Median Filter 6.多维树状数组模型 四.树状数组题集整理 一.从图形学算法说起 1.M