【问题标题】:The two pointer algorithm二指针算法
【发布时间】:2017-04-06 10:01:07
【问题描述】:

我正在尝试理解双指针算法的方法,所以我一直在阅读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 并重复该过程。

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

【问题讨论】:

  • 您忘记了不仅 l 增加了,而且前一个 L-th 元素的值也从总和中减去。然后总和包含新的LR 之间的所有剩余元素,不需要重新计算这个总和(使用R = L 重新启动循环)。我也认为(没有阅读文章)有一个隐含的要求元素> = 0,因此总和只能增长。

标签: algorithm greedy


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

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

    如果整数可以是负数,那你是对的,这不起作用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-13
      • 1970-01-01
      • 2016-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-01
      相关资源
      最近更新 更多