我正在尝试理解两种指针算法的方法,所以我一直在阅读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
并重复该过程。
我看不出这是如何产生正确结果的。
答案 0 :(得分:4)
该方法有效,因为对于每个r
指针,当前l
实际上代表左边最远的一个,使得总和仍然低于阈值。
因此,没有必要查看以r
指针结尾的所有其他序列。
但是,如果允许使用负数,则该方法无效。在这种情况下,较长的l
- r
序列并不一定意味着总和会增加。
答案 1 :(得分:2)
该算法有效。它假设数组中的所有值都是正数(或0),因此对于固定的l,可以通过while循环找到从l开始的最佳连续序列,方法是添加正或零元素直到当前总和达到之前的最后一个r M.
到那时你知道从l开始并且在r之前停止的序列小于当前的序列,并且在r之后停止的序列太大(> M)。因此,您只需将当前总和与之前的最佳值进行比较,然后继续使用l。
的下一个值如果整数可能是负数,那么你说这是行不通的。