LA 2678 subsequece 子序列

题目大意
给定有n个正整数构成的序列和整数S,求长度最短的连续序列,使他们的和等于S
分析
首先想到的方法就是暴力枚举,,枚举起点和终点

for (int i = 0; i < n; i++)
	for (int j = i; j < n; j++)
			{
				int sum = 0;
				for (int k = i; k <= j; k++)
					sum = sum + q[k];
				if (sum >= m)
					ans = min(ans, j - i + 1);
			}

暴力的复杂较高,我们使用前缀和的方式降低复杂度令sum(i)=P1+P2+………Pi

		sum[0] = 0;
		for (int i = 1; i <= n; i++)
			sum[i] = sum[i - 1] + q[i];
		for (int i = 1; i <= n; i++)
		{
			for (int j = i; j <= n; j++)
				if (sum[j] - sum[i] >= m)
					ans = min(ans, j - i);
		}

对于一些数据量较大的情况复杂度还是很大,我们再次尝试优化,只要枚举起点和终点就一定无法降维,我们另谋他路.尝试只枚举终点,或者只枚举起点。
我们试一试枚举终点,对于终点j说我们要找到最小的i,i应该满足什么条件呢 qj-s>=qi,在满足此条件的情况下寻找最大的j,因为是正整数序列,所以S数组一定是递增的。我们可以使用二分查找
核心代码

	for (int i = 1; i <= n; i++)
		sum[i] = sum[i - 1] + q[i];
	int ans = n + 1;
	for (int j = 1; i < n; i++) {
		int i = lower_bound(sum, sum + j, sum[j] - s) - sum;
		if (i > 0) ans = min(ans, j - i + 1);
	}

关于二分查找,详见大佬lower_bound和upper_bound
还有一种不用二分查找的方法,因为sum是递增的,j是递增的那么i也一定是递增的

for (int i = 1; i <= n; i++)
			sum[i] = sum[i - 1] + q[i];
		int i = 1,ans=n+1;
		for (int j = 1; j <= n; j++)
		{
			if (sum[j] - m <= sum[i-1])	continue;
			while (sum[j] - sum[i] >= m) i++;
			ans = min(ans, j - i + 1);
		}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值