解 减时间复杂度

又是一个能让人眼前一亮的题,解的时候qiuqiu带感

一串整数a[1]…a[n],求子序列最大和,让算法复杂度最理想

plan A

不难想出

按照题目要求推

需要三次循环,复杂度为O(n^3),显然不是最优解

光荣下岗

#include<bits/stdc++.h>
using namespace std;

int main() {
	int a[107],n;
	scanf("%d",&n);
	for(int i=1; i<=n; i++)//输入数组
		scanf("%d",&a[i]);
	int maxn=a[1];
	for(int i=1; i<=n; i++) {//第一层循环
		for(int j=i,sum=0; j<=n; j++) {//第二层循环
			for(int k=i; k<=j; k++)//第三层循环
				sum+=a[k];
			if(sum>maxn) maxn=sum; } }
	printf("%d",maxn);
	return 0; }

plan B

智慧结晶plan B应运而生

可以三层循环降二层循环降一次循环

换个角度考虑问题,选择角度相对

加改为前缀和,乘改为除,开方改为平方,最大改为最小

降循环次数,需要多写一个一维循环

#include<bits/stdc++.h>
using namespace std;

int main() {
	int a[107],s[107],n;
	scanf("%d",&n);
	for(int i=1; i<=n; i++) scanf("%d",&a[i]);
	int maxn=a[1];
	s[1]=a[1];
	for(int i=2; i<=n; i++)
		s[i]=a[i]+s[i-1];//进行化简
	for(int i=1; i<=n; i++)//第一层循环
		for(int j=1; j<=n; j++)//第二层循环
			if(s[j]-s[i-1]>maxn)
				maxn=s[j]-s[i-1];
	printf("%d",maxn);
	return 0; }

时间复杂度是O(n^2),有所改进

plan A对于每一个i 通过每一个j 找到一个最大值(需要k 的参与),将这些最大值进行比较

plan B则通过一次循环简化掉k ,把求最大值的过程简单化了

将重复多次的加和运算变为一次性计算过的循环计算

把不同的计算变为一致的计算

plan C

对于每一个i 通过每一个j 的方法并不绝对简便

plan B省略了k,那能否省略j 

奥夫考斯

#include<bits/stdc++.h>
using namespace std;

int main() {
	int a[107],s[107],n;
	scanf("%d",&n);
	for(int i=1; i<=n; i++)
		scanf("%d",&a[i]);
	int maxn=a[1],minn=a[1];
	s[1]=a[1];
	for(int i=2; i<=n; i++)
		s[i]=a[i]+s[i-1];//进行化简
	for(int i=1; i<=n; i++) {
		if(s[i]<minn) minn=s[i];//确保i(min)在前,i(max)在后
		if(s[i]-minn>maxn) maxn=s[i]-minn; }
	printf("%d",maxn); }

改循环为变量交换

理解简单

与plan B相似,时间复杂度O(n)

plan D

是我最先的思路

把每一项与前一项相加,得到新的数组

再按照递归的思路,重复操作

当化简到最简数组时,就可通过每一项的数值求出最大值

但实施起来显然没有plan C简便

一来递归的出口不易找到;二来没有在大的全局的考量,导致解法复杂


顺便吐槽一下拖延症晚期的神通

2021.12.04

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值