Two pointer techniques — a visual tutorial

Three animated two-pointer techniques to solve Three different problems.

Andreas Klintberg
6 min readAug 3, 2022
Photo by Paul Hanaoka on Unsplash

As a self-taught developer (no theoretical CS background), learning data structures and algorithms later in your career is crucial.

One of the algorithms or techniques widely used for both array and linked list problems is the “two-pointer technique”. There are a range of different variations of this that can be applied to a range of problems:

  • Starting from both ends of the array, a left pointer at the start (0) and a right pointer at the end of the array.
  • Slow and fast pointer, one pointer moving slow (1 step for instance) and another moving fast (2 steps or variable number of steps).
  • Starting from 2 different arrays, for merging etc.
  • Split array and then start a pointer from each.
  • 2 slow pointers starting from the beginning of the array, variable / sliding window technique.

Very versatile and applicable to a range of different problems, as you can see in this excellent guide on Leetcode by chuka231 [1].

Yet another tutorial?

Why put time into writing yet another two-pointer tutorial? There are a bunch of resources out there doing a great job of explaining this technique, both on Youtube and in text [5] [6][8].
Personally I felt it was sometimes difficult to grasp what was happening while doing a dry run. Seeing the change in values, and the pointer position over the array(s) would accelerate my learning and understanding. Seeing the tutorial [8] by LeetDev on Youtube, inspired me to do something similar in blog format.

Problems and walkthrough

Let’s walk through three different pointer techniques and problems that can be solved with them; visualizing the algorithmic solution for each.

167. Two Sum II — Input Array Is Sorted [2]

Starting from both ends of the array. This problem is described as

Given a 1-indexed array of integers numbers that is already sorted in non-decreasing order, find two numbers such that they add up to a specific target

For this problem one pointer will start at the beginning, called left, and another at the far end, called right. The trick here is using the fact that the array is sorted, meaning if the sum of arr[left] + arr[right]is bigger than the target, we’ll move the right pointer one step to the left, and a smaller number. If it’s smaller than the target we move the left pointer to the right, and a bigger number.

left, right = 0, len(arr) - 1

while left <= right:

if arr[left] + arr[right] == target:
return [left + 1, right + 1]
elif arr[left] + arr[right] > target:
right -= 1
else:
left += 1
return False

This way we’ll eventually find the target sum, or return false when the two pointers meet, meaning the target sum could not be found. How does this look? Pretty straight forward, but still intriguing!

Moving pointers and checking the sum at each step if it equals the target 9 (2 + 7) in this case.

283. Move Zeroes [3]

Fast and slow pointer; this problem is described as

Given an integer array nums, move all 0's to the end of it while maintaining the relative order of the non-zero elements.

In order to solve this we initialize the fast and slow pointer, to the same position, the first index. The trick here is to let the slow pointer move if and only if it’s not a 0, and the fast pointer will move 1 step each loop. This way, the slow will only ever walk as far as there are non-zeros in the array, and the fast will walk all the way to the end.

slow = 0
for fast in range(len(arr)):
if arr[fast] != 0:
arr[slow], arr[fast] = arr[fast], arr[slow]
slow += 1

What happens next is that we swap the value at the slow pointer with the value at the fast pointer. Tricky? Let’s see how it actually looks:

Moving pointers and swapping values. Zeros are eventually all at the end of the array

209. Minimum Size Subarray Sum [4]

Two pointers starting starting from the beginning, variable / sliding window technique.

Given an array of positive integers nums and a positive integer target, return the minimal length of a contiguous subarray [numsl, numsl+1, ..., numsr-1, numsr] of which the sum is greater than or equal to target

The trick here is to read the description very carefully; it’s fine as long as you find a contiguous subarray equal OR greater than the target. Another very important point in the constraints, is that the nums will always be positive integers bigger than 0. Meaning the number will always increase as you move forward. Last important point is that the subarray can actually be 1, meaning 1 value is fine if it’s equal to or larger than our target.

We start our two pointers at the very start of the array, and check if it’s larger than the target. Thereafter we’ll move the right pointer to the right until we get to a number equal to or larger than our target. We record the length of the distance between the left pointer and the right pointer and then we move the left pointer one step to see if we are still larger than the target, if so we record that new length as well. We try to move it again and again until it’s smaller than the target, then we move the right pointer again. Finally the left and right pointer will both be at the end of the array and we’ll have saved all the lengths between pointer left and right. Now return the min of the array of saved lengths. One could optimize the space requirement and just save the min as a scalar and take the minimum as one loops through.

# if the first number is larger or equal to target, min is 1
if nums[0] >= target:
return 1

cum_sum = left = 0
min_len = len(nums) + 1

for right in range(len(nums)):
cum_sum += nums[right]

# do not run until cum_sum is greater than or equal to target
while cum_sum >= target:
min_len = min(min_len, right - left + 1)
cum_sum -= nums[left]
left += 1

return min_len if min_len <= len(nums) else 0

So after a convoluted description, let’s look at how simple the animation is

Moving pointers and checking the minimum length subarray that are greater than or equal to target 7

Conclusions

Reflecting over why I sometimes have trouble simulating the pointers and values of the array for simple test cases, might stem from the trial and error type process I followed as I started as a developer. Learning things from theory first in a classroom forces you to simulate and dry run whatever is happening. Learning while building I offloaded a lot of my brain capacity to the computer and just ran the code a bunch of times to see whatever worked. I made a mental note of what particular things worked.

Hopefully these animations will make it easier for you to eventually be able to effortlessly simulate pointers traversing arrays, and solving problems without needing to write a line of code before it’s fully solved in your head.

I started out building simple, crude animations using PyGame [7], before thinking of Manim. If you want to check out thecode you’ll find it here https://github.com/klintan/two-pointer-animator (fair warning, it’s not pretty)

References

[1] https://leetcode.com/discuss/study-guide/1688903/Solved-all-two-pointers-problems-in-100-days.

[2] https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/

[3] https://leetcode.com/problems/move-zeroes/

[4] https://leetcode.com/problems/minimum-size-subarray-sum/

[5] https://medium.com/swlh/using-the-two-pointer-technique-bf642ab05661

[6] https://cdragon.medium.com/basics-of-two-pointers-technique-e1a0df57ba7e — Nice animated pointers in this blog post

[7] https://github.com/klintan/two-pointer-animator

[8] https://www.youtube.com/watch?v=On03HWe2tZM&ab_channel=LeetDev

--

--