Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The two pointer algorithm

I'm trying to understand the two pointer algorithm approach, so I've been reading this article

So here is the question. Suppose we have an array of N elements. And we want to find the largest contiguous sequence of elements in that array where the sum is less than or equal to M. We have to return the value that the sequence of elements sums up to.

So suppose we have an array of elements [2, 1, 3, 4, 5] and our M is 12. We would return 12 because 3, 4, and 5 sum up to 12. Here was the approach from the article

  • We introduce two pointers l, r denoting startIndex and endIndex of our contiguous subarray, with both of them at the tip of the array.
  • We now start extending our right pointer r provided sum[l,r] <= M Once, we reach at such a stage, we don't have any option but to move the left pointer as well and start decreasing the sum until we arrive at the situation where we can extend our right pointer again.
  • As and when we reach the point, where we need to shift the left pointer, we keep updating our maximum sum we have achieved so far.

And here was the C++ code.

#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;
}

But I don't understand why this approach works. We are not considering all possible contiguous sub sequences. As soon as the sum is exceeded, we take note of our current sub sequence length, compare it to see if it's larger than the previous one, and simply increment l and repeat the process.

I don't see how this yields the correct result.

like image 310
Rockstar5645 Avatar asked Apr 06 '17 10:04

Rockstar5645


People also ask

What is the two pointers algorithm?

Two pointer algorithm is one of the most commonly asked questions in any programming interview. This approach optimizes the runtime by utilizing some order (not necessarily sorting) of the data. It is generally applied on lists (arrays) and linked lists. This is generally used to search pairs in a sorted array.

What is pointer algorithm?

The Jump pointer algorithm is a design technique for parallel algorithms that operate on pointer structures, such as arrays or linked list. This algorithm is normally used to determine the root of the forest of a rooted tree.

Where is a 2 pointer?

A 2-pointer in basketball is a shot scored anywhere inside the three-point arch. This includes the paint, midrange and at the rim. All of these shots count for two points, unless taken from the free-throw line for a foul shot.

How do you solve a two pointer problem?

One pointer starts from the beginning while the other pointer starts from the end. The idea is to swap the first character with the end, advance to the next character and swapping repeatedly until it reaches the middle position. We calculate the middle position as ⌊ n 2 ⌋ \lfloor\frac{n}{2}\rfloor ⌊2n⌋.


2 Answers

The approach works because for each r pointer, the current l actually represents the furthest one to the left such that the sum is still below the threshold.

Therefore it is not necessary to look into all other sequences that end at the r pointer.

However, the approach is not valid if negative numbers would be allowed. In that case, a longer l - r sequence would not necessarily mean that the sum would increase.

like image 180
qwertyman Avatar answered Oct 11 '22 06:10

qwertyman


The algorithm works. It assumes all values in the array are positive (or 0), so for a fixed l, the best contiguous sequence starting at l can be found by the while loop, by adding positive or zero elements until the last r before your current sum reaches M.

By then you know that sequences starting at l and stopping before r are smaller than the current one, and that the ones stopping after r are just too big (>M). So you just compare the current sum to the previous best, and you move on to next value for l.

If the integers can be negative, you're right that this does not work.

like image 29
gdelab Avatar answered Oct 11 '22 06:10

gdelab