最大字段和(洛谷p1115) 题解

本文通过逐步解析介绍了如何使用动态规划解决寻找数组中最长连续字段和的问题。从最初的暴力求解导致超时,到优化算法减少重复计算,再到最后采用动态规划思路实现线性时间复杂度的解决方案,作者详细阐述了整个思考和优化过程,并给出了最终的高效代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最大字段和洛谷p1115 题解

写的比较多(good),承认自己比较菜,但是自认为还是写的挺细的,至少把我思考的全过程都写了。

看题

在这里插入图片描述

首先看题目,很好理解。

就是求一个数组中,最长的连续区间。

题解1

我们对这个字符串进行遍历,

图1

代码如下:
#include <iostream>
using namespace std;
int main(){
	static int N[200000];
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>N[i];
	}
	int s=0;
    int S=0;
    for(int i=0;i<n;i++){
        for(int j=i;j<n;j++){
        	s=0;
			for(int z=i;z<j;z++)
        		s+=N[z];
    		S=S>s?S:s;
		}
    }
	cout<<S<<endl;
	return 0;
}

这个代码的复杂度是O(n3),为什么呢?因为我们用i确定的是端点左侧,用j确定的是端点右侧,又加上这个区域里的所有的数,是三层循环。

图2

结果:

图3

显然,这样会超时,但是我们可以算出样例:

图4

题解2

图5

我们在算——例如2,-4和2,-4,3时,我们重复算了【2】+【-4】这一过程,那么,我们可以减少一下运算,我们可以对已经计算过的数据进行保留,这样就可以减少我们的代码量了。

图6

代码如下:
#include <iostream>
using namespace std;
int main(){
	static int N[200000];
	static int p[200000][200000];
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>N[i];
	}
    int S=0;
    for(int i=0;i<n;i++){
        for(int j=i;j<n;j++){
        	p[i][0]=0;
			p[i][j]=p[i][j-1]+N[j];
    		S=S>p[i][j]?S:p[i][j];	
		}
    }
	cout<<S<<endl;
	return 0;
}

此时的时间复杂度是O(n2)

图7

当然,这样还不是最优的结果

题解2+

你可以想一下,如果用树对这个进行存储,会不会更加简单一点呢?

大概时间复杂度应该是O(n*longn)

题解3

我们却发现我们还是对这个数据有重复使用,我们怎么处理呢?

思考

图8

我们以这三个数为例,我们如果是算出2+(-4)=-2,那么,我们明显能看到,2这个数据已经使用过了,没有用了,我们是不是就可以把2抛弃

在-2和-4中选择。

这样,我们只用一个指针就可以算出了,但是,这时候,我们却发现,2如果也可以成为最优的解呢?

假如是这种情况呢?(如图)

图9

这时,我们就想到,我们的最终目的只是找出谁最大,那么我们何不这么解决的呢?

图10

我们用动态规划的思想,在第k位的时候,我们想,我们有两个选择,要还有不要,这样我们就可以遍历出所有的过程,当然,如果我们在过程中出现这样的情况

图11

当我们的指针指向第1位时,我们选择了5+(-4)的解,而舍弃了-4,但是,我们却同时也没有考虑之前5的解,我们就想到了,我们可以记录每次选择的最优的解,比如,第一次指针指到5时的5,每次选择后,我们不仅继续推进,也保留当前的最优解。

#include <iostream>
using namespace std;
int main(){
	static int N[200000];
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>N[i];
	}
	int s=N[0];
    int S=s;
    for(int i=1;i<n;i++){
        s=N[i]+s>N[i]?N[i]+s:N[i];
        S=S>s?S:s;
    }
	cout<<S<<endl;
	return 0;
}
演示动画(这是一个动画)

最大字段和动画

课后反思

其实,我们也可以每次比较之前累加的s是不是大于0,就可以知道加上本位是不是会更优。

s=s>0?N[i]+s:N[i];

可以对这个算法进行进一步的优化。

实例
7
2 -4 3 -1 2 -4 3
注释

我们为什么使用static ,因为静态的static int 数组可以存更多的数,这样不容易爆掉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

推演者

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

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

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

打赏作者

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

抵扣说明:

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

余额充值