两个指针算法

时间:2017-04-06 10:01:08

标签: algorithm greedy

我正在尝试理解两种指针算法的方法,所以我一直在阅读this article

所以这就是问题所在。假设我们有一个N元素的数组。我们希望找到该数组中最大的连续元素序列,其中和小于或等于M.我们必须返回元素序列总和的值。

假设我们有一个元素数组[2,1,3,4,5],我们的M是12。 我们将返回12,因为3,4和5总计为12.这是文章中的方法

  • 我们引入了两个指针lr表示我们连续子阵列的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并重复该过程。

我看不出这是如何产生正确结果的。

2 个答案:

答案 0 :(得分:4)

该方法有效,因为对于每个r指针,当前l实际上代表左边最远的一个,使得总和仍然低于阈值。

因此,没有必要查看以r指针结尾的所有其他序列。

但是,如果允许使用负数,则该方法无效。在这种情况下,较长的l - r序列并不一定意味着总和会增加。

答案 1 :(得分:2)

该算法有效。它假设数组中的所有值都是正数(或0),因此对于固定的l,可以通过while循环找到从l开始的最佳连续序列,方法是添加正或零元素直到当前总和达到之前的最后一个r M.

到那时你知道从l开始并且在r之前停止的序列小于当前的序列,并且在r之后停止的序列太大(> M)。因此,您只需将当前总和与之前的最佳值进行比较,然后继续使用l。

的下一个值

如果整数可能是负数,那么你说这是行不通的。