Mark As Completed Discussion

The Two Pointer Technique

The two pointer technique is a near necessity in any software developer's toolkit, especially when it comes to technical interviews. In this guide, we'll cover the basics so that you know when and how to use this technique.

Introduction

What is the pattern?

The name two pointers does justice in this case, as it is exactly as it sounds. It's the use of two different pointers (usually to keep track of array or string indices) to solve a problem involving said indices with the benefit of saving time and space. See the below for the two pointers highlighted in yellow.

But what are pointers? In computer science, a pointer is a reference to an object. In many programming languages, that object stores a memory address of another value located in computer memory, or in some cases, that of memory-mapped computer hardware.

What Is The Pattern?

When do we use it?

In many problems involving collections such as arrays or lists, we have to analyze each element of the collection compared to its other elements.

There are many approaches to solving problems like these. For example we usually start from the first index and iterate through the data structure one or more times depending on how we implement our code.

Sometimes we may even have to create an additional data structure depending on the problem's requirements. This approach might give us the correct result, but it likely won't give us the most space and time efficient result.

This is why the two-pointer technique is efficient. We are able to process two elements per loop instead of just one. Common patterns in the two-pointer approach entail:

  1. Two pointers, each starting from the beginning and the end until they both meet.
  2. One pointer moving at a slow pace, while the other pointer moves at twice the speed.

These patterns can be used for string or array questions. They can also be streamlined and made more efficient by iterating through two parts of an object simultaneously. You can see this in the Two Sum problem or Reverse a String problems.

Build your intuition. Could you figure out the right sequence for this list?

Order the following steps according to the general steps required for solving a problem using two-pointer technique.

Press the below buttons in the order in which they should occur. Click on them again to un-select.

Options:

  • Initialize two pointers
  • Reduce the problem to a search problem
  • Update pointers
  • Evaluate the elements pointed by pointers

Running through an example

One usage is while searching for pairs in an array. Let us consider a practical example: assume that you have a sorted array arr.

You're tasked with figuring out the pair of elements where arr[p] + arr[q] add up to a certain number. (To try this problem out, check the Two Sum and Sorted Two Sum problems here.)

The brute force solution is to compare each element with every other number, but that's a time complexity of O(n^2). We can do better!

So let's optimize. You need to identify the indices pointer_one and pointer_two whose values sum to the integer target.

Let's initialize two variables, pointer_one and pointer_two, and consider them as our two pointers.

1pointer_one = 0
2pointer_two = len(arr) - 1

These snippets declare two pointers, typically used to traverse an array or a similar data structure. In C++, the calculation of pointerTwo assumes that arr is a statically defined array. If it were a dynamic array or a standard container like std::vector, you would use arr.size() instead.

Note that len(arr)-1 helps to get the last index possible in an array.

Also observe that when we start, pointer_one points to the first element of the array, and pointer_two points to the last element.

This won't always be the case with this technique (we'll explore the sliding window concept later, which uses two pointers but have them move in a different direction). For our current purposes, it is more efficient to start wide, and iteratively narrow in (particularly if the array is sorted).

1def two_sum(arr, target):
2    pointer_one = 0
3    pointer_two = len(arr) - 1
4
5    while pointer_one < pointer_two:
6        # logic to find the two numbers that add up to target

Since the array is already sorted, and we're looking to process an index at each iteration, we can use two pointers to process them faster. One pointer starts from the beginning of the array, and the other pointer begins from the end of the array, and then we add the values at these pointers.

Once we're set up, what we want to do is check if the current pointers already sum up to our target. This might happen if the correct ones are on the exact opposite ends of the array.

Here's what the check might look like:

1if sum == target:
2    return True

These snippets implement the logic to check if the sum of two numbers from an array equals the target value, returning the appropriate result. In Python, the code snippet returns a boolean value, while the other languages return the indices or values of the two numbers that add up to the target.

However, it likely will not be the target immediately. Thus, we apply this logic: if the sum of the values is less than the target value, we increment the left pointer (move your left pointer pointer_one one index rightwards).

And if the sum is higher than the target value, we decrement the right pointer (correct the position of your pointer pointer_two if necessary).

1} else if (arr[left] + arr[right] < target) {
2    left++;
3} else {
4    right--;
5}

In other words, understand that if arr[pointer_one] < target-arr[pointer_two], it means we should move forward on pointer_one to get closer to where we want to be in magnitude.

This is what it looks like all put together:

CSHARP
OUTPUT
:001 > Cmd/Ctrl-Enter to run, Cmd/Ctrl-/ to comment

It's crucial to see that how both indices were moving in conjunction, and how they depend on each other.

We kept moving the pointers until we got the sum that matches the target value-- or until we reached the middle of the array, and no combinations were found.

The time complexity of this solution is O(n) and space complexity is O(1), a significant improvement over our first implementation!

Another Example

In addition, to the previous example, the two pointer technique can also involve the pattern of using a fast pointer and a slow pointer.

1Node fast = head, slow = head;

One usage is through detecting cycles in a linked list data structure. For example, a cycle (when a node points back to a previous node) begins at the last node of the linked list in the example below.

Step Ten
TEXT
OUTPUT
:001 > Cmd/Ctrl-Enter to run, Cmd/Ctrl-/ to comment

The idea is to move the fast pointer twice as quickly as the slow pointer so the distance between them increases by 1 at each step.

Step Eleven
1while (fast != null && fast.next != null) {
2  slow = slow.next;
3  fast = fast.next.next;
4}

However, if at some point both pointers meet, then we have found a cycle in the linked list. Otherwise we'll have have reached the end of the list and no cycle is present.

Step Twelve
CSHARP
OUTPUT
:001 > Cmd/Ctrl-Enter to run, Cmd/Ctrl-/ to comment

The attached code is what the entire method would look like all together.

The time complexity would be O(n) or linear time.

CSHARP
OUTPUT
:001 > Cmd/Ctrl-Enter to run, Cmd/Ctrl-/ to comment

Try this exercise. Is this statement true or false?

Two pointer technique can improve both the time and space complexity of a problem.

Press true if you believe the statement is correct, or false otherwise.

Are you sure you're getting this? Fill in the missing part by typing it in.

Consider a problem where two sorted arrays need to be merged. Two-pointers will be required for ___ array/arrays.

Write the missing line below.

Build your intuition. Click the correct answer from the options.

Reversing words in a string is a problem that can be solved by two-pointer technique. How should the two pointers be used?

Click the option that best answers the question.

  • Both pointers placed at the beginning of array
  • Pointers placed at beginning and end of array
  • Pointer placed at first and second element of array
  • None of the above

One Pager Cheat Sheet

  • The Two Pointer Technique is an essential tool for software developers to use, especially when faced with technical interviews.
  • Pointers are references to objects, and the two pointers technique is used to track and compare array or string indices to save time and space.
  • The two-pointer technique is an efficient approach to processing two elements of a data structure, such as an array or list, per loop in order to solve problems involving collections.
  • The two-pointer technique is a search algorithm used to solve problems involving collections such as arrays and lists by comparing elements pointed by two pointers and updating them accordingly.
  • By initializing two variables pointer_one and pointer_two and evaluating their values with respect to the given target, we can find pairs in an array that sum up to a certain number with a O(n) time complexity.
  • Two pointers are used in different programming languages to start from the ends of an array and iteratively narrow in to find thetarget` more efficiently than other techniques.
  • We can use two pointers starting from the beginning and end of an already sorted array to check if they 'sum up' to the target, which is done by a simple comparison statement if sum == target.
  • The logic applied is to increment the left pointer if the sum of values is less than the target value and decrement the right pointer if it is higher than the target value.
  • Understand that if arr[pointer_one] < target-arr[pointer_two], pointer_one should be moved forward to get closer to the desired magnitude.
  • The process of using a fast pointer and a slow pointer is another way to apply the two pointer technique, which can have O(n) time complexity and O(1) space complexity.
  • Using Slow and Fast Pointers can detect cycles in a linked list, such as when a node points back to a previous node.
  • By setting fast to traverse twice as quickly as slow, the distance between them increases at each step.
  • If both pointers reach the same node, then there is a cycle present in the linked list.
  • The code attached provides an O(n) or linear time complexity.
  • Yes, the two pointer technique can reduce both time and space complexity down to O(n), thus improving overall performance.
  • Two-pointers are useful for iterating over and combining two sorted arrays.
  • The two-pointer technique involves placing two pointers at opposite ends of an array and comparing their values to reverse its order by swapping or shifting items.