【发布时间】:2017-04-06 10:01:07
【问题描述】:
我正在尝试理解双指针算法的方法,所以我一直在阅读this article
所以问题来了。假设我们有一个包含 N 个元素的数组。我们想在该数组中找到最大的连续元素序列,其中总和小于或等于 M。我们必须返回元素序列总和的值。
所以假设我们有一个元素数组 [2, 1, 3, 4, 5],我们的 M 是 12。 我们将返回 12,因为 3、4 和 5 之和为 12。这是文章中的方法
- 我们引入了两个指针
l、r,分别表示我们连续子数组的 startIndex 和 endIndex,它们都位于数组的顶端。 - 我们现在开始扩展我们的右指针
r提供sum[l,r] <= M一旦,我们到达这样一个阶段,我们别无选择,但 也移动左指针并开始减少总和,直到 我们到达了可以扩展右指针的情况 再次。 - 当我们到达点时,我们需要向左移动 指针,我们会不断更新我们迄今为止达到的最大总和。
这里是 C++ 代码。
#include <bits/stdc++.h>
#define lli long long
#define MAX 1000005
using namespace std;
lli A[MAX];
int main()
{
int n;
lli sum = 0;
cin >> n;
for ( int i = 0; i < n; i++ ) cin >> A[i];
int l = 0, r = 0;
lli ans = 0;
while ( l < n ) {
while ( r < n && sum + A[r] <= M ) {
sum += A[r];
r++;
}
ans = max(ans, sum);
sum -= A[l];
l++;
}
cout << ans << endl;
return 0;
}
但我不明白为什么这种方法有效。我们没有考虑所有可能的连续子序列。一旦超过总和,我们就记下我们当前的子序列长度,比较它是否大于前一个,然后简单地增加l 并重复该过程。
我看不出这是如何产生正确结果的。
【问题讨论】:
-
您忘记了不仅 l 增加了,而且前一个
L-th 元素的值也从总和中减去。然后总和包含新的L和R之间的所有剩余元素,不需要重新计算这个总和(使用R = L重新启动循环)。我也认为(没有阅读文章)有一个隐含的要求元素> = 0,因此总和只能增长。