Data Structure and Algorithm
The Two Pointers Method with Three Practical Examples
- Introduction
- Different Types of Two Pointers
- Applications of the Two Pointers Technique
- Run C Programming Online Compiler
¶Introduction
The two-pointer technique is a common algorithmic approach used to solve problems involving arrays, linked lists, and strings. It involves using two pointers to traverse through the data structure efficiently. This method is particularly useful when dealing with sorted arrays or linked lists, as it can often reduce time complexity compared to brute force approaches.
¶Different Types of Two Pointers
¶Two pointers moving in opposite directions
Useful for problems like finding pairs with a specific condition in a sorted array. let’s consider the following problem,
Given a sorted array of integers and a target sum, find two numbers in the array that add up to the target sum.
Solution:
We can solve this problem using two pointers method where two pointers will move towards opposite directions.
- Place one pointer (
left
) at the beginning of the array and the other pointer (right
) at the end. - Calculate the sum of the elements at the left and right pointers.
- If the sum equals the target, return the indices.
- If the sum is less than the target, move the left pointer to the right to increase the sum.
- If the sum is greater than the target, move the right pointer to the left to decrease the sum.
- Repeat the sum calculation and condition checking until the left pointer is no longer less than the right pointer.
Implementation in C++:
#include <bits/stdc++.h>
using namespace std;
pair<int, int> findTwoSum(const vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1;
while (left < right) {
int sum = nums[left] + nums[right];
if (sum == target) {
return {left, right};
} else if (sum < target) {
left++;
} else {
right--;
}
}
return {-1, -1}; // Return -1, -1 if no pair is found
}
int main() {
vector<int> nums = {1, 2, 3, 4, 6, 8, 11, 15};
int target = 10;
pair<int, int> result = findTwoSum(nums, target);
if (result.first != -1) {
cout << "Pair found at indices: " << result.first << " and " << result.second << endl;
} else {
cout << "No pair found." << endl;
}
return 0;
}
Pair found at indices: 1 and 5
Time and Space Complexity
Time complexity: O(n)
Space complexity: O(n)
¶Two pointers moving at different speeds
Useful for problems like finding sub-arrays with a specific condition. let’s consider the following problem,
Given an array of integers, find the length of the longest sub-array that contains no duplicate numbers.
Solution:
we can use the sliding window and two pointers technique along with a map data-structure.
- Use two pointers,
left
andright
, to represent the current window. - Use an map to store the frequency of elements in the current window.
- Iterate with the
right
pointer from the start to the end of the array. For each element at right, check if it is already in the map. - If it is not in the map, add it and update the maximum length.
- If it is in the map, shrink the window from the left until the element at right can be added without duplicates.
- Continuously update the maxLength variable with the size of the current window if it is larger than the previously recorded maximum length.
Implementation in C++:
#include<bits/stdc++.h>
using namespace std;
int longestUniqueSubarray(const vector<int>& nums) {
map<int, int> elementCount;
int left = 0, right = 0, maxLength = 0;
while (right < nums.size())
{
while (elementCount[nums[right]] > 0)
{
elementCount[nums[left]]--;
++left;
}
elementCount[nums[right]]++;
maxLength = max(maxLength, right - left + 1);
++right;
}
return maxLength;
}
int main() {
vector<int> nums = {2, 3, 4, 5, 2, 7, 4, 6, 8, 9};
cout << "The length of the longest subarray without duplicate numbers is: "
<< longestUniqueSubarray(nums) << endl;
return 0;
}
The length of the longest subarray without duplicate numbers is: 7
Time and Space Complexity
Time complexity: O(nlog(n))
Space complexity: O(n)
¶Two pointers on different arrays
Useful for problems like merging two sorted arrays on a condition. let’s consider the following problem,
Given two sorted arrays, merge them into a single sorted array.
Solution:
To merge two sorted arrays, we can use a two-pointer technique to efficiently combine the elements in sorted order. The idea is to traverse both arrays simultaneously, comparing elements and placing the smaller one into the result array.
- Use two pointers,
i
andj
, to traverse the first and second arrays, respectively. - Compare the current elements of both arrays (pointed to by
i
andj
). - Place the smaller element into the result array and move the corresponding pointer to the next element.
- If there are remaining elements in one array, append all the elements of the other array to the result array.
- Repeat this process until both of the arrays are fully traversed.
Implementation in C++:
#include<bits/stdc++.h>
using namespace std;
vector<int> mergeSortedArrays(const vector<int>& arr1, const vector<int>& arr2) {
vector<int> mergedArray;
int i = 0, j = 0;
// Traverse both arrays
while (i < arr1.size() && j < arr2.size()) {
if (arr1[i] < arr2[j]) {
mergedArray.push_back(arr1[i]);
i++;
} else {
mergedArray.push_back(arr2[j]);
j++;
}
}
// Add remaining elements of arr1
while (i < arr1.size()) {
mergedArray.push_back(arr1[i]);
i++;
}
// Add remaining elements of arr2
while (j < arr2.size()) {
mergedArray.push_back(arr2[j]);
j++;
}
return mergedArray;
}
int main() {
vector<int> arr1 = {1, 3, 5, 7};
vector<int> arr2 = {2, 4, 6, 8};
vector<int> result = mergeSortedArrays(arr1, arr2);
cout << "Merged array: ";
for (int num : result) {
cout << num << " ";
}
cout << endl;
return 0;
}
Merged array: 1 2 3 4 5 6 7 8
Time and Space Complexity
Time complexity: O(n + m)
Space complexity: O(n + m)
¶Applications of the Two Pointers Technique
-
Cycle Detection: Hare and Tortoise Algorithm : Detects cycles in linked lists. One pointer (tortoise) moves one node at a time, while the other (hare) moves two nodes at a time. If there’s a cycle, they will eventually meet.
-
Array/List Traversal : Iterates through arrays or linked lists efficiently. Often used for finding pairs, triplets, or specific elements with certain conditions.
-
Sorting Algorithms : Used in algorithms like Quick Sort and Merge Sort. Helps partition arrays or merge sorted subarrays.
-
String Manipulation : palindrome checking, finding substrings, anagram checking.
-
Geometric Algorithms : Used in computational geometry problems. Involves operations like finding intersections, calculating distances, and analyzing shapes.
¶Run C Programming Online Compiler
To make your learning more effective, exercise the coding examples in the text editor below.
Introduction to Binary Search with Practical Examples
All Tutorials in this playlist
Popular Tutorials
Categories
-
Artificial Intelligence (AI)
11
-
Bash Scripting
1
-
Bootstrap CSS
0
-
C Programming
14
-
C#
0
-
ChatGPT
1
-
Code Editor
2
-
Computer Engineering
3
-
CSS
28
-
Data Structure and Algorithm
18
-
Design Pattern in PHP
2
-
Design Patterns - Clean Code
1
-
E-Book
1
-
Git Commands
1
-
HTML
19
-
Interview Prepration
2
-
Java Programming
0
-
JavaScript
12
-
Laravel PHP Framework
37
-
Mysql
1
-
Node JS
1
-
Online Business
0
-
PHP
28
-
Programming
8
-
Python
12
-
React Js
19
-
React Native
1
-
Redux
2
-
Rust Programming
15
-
SEO - Search Engine Optimization
1
-
Tailwind CSS
1
-
Typescript
10
-
Uncategorized
0
-
Vue JS
1
-
Windows Operating system
1
-
Woocommerce
1
-
WordPress Development
2
Tags
- Artificial Intelligence (AI)
- Bash Scripting
- Business
- C
- C Programming
- C-sharp programming
- C++
- Code Editor
- Computer Engineering
- CSS
- Data Structure and Algorithm
- Database
- Design pattern
- Express JS
- git
- Git Commands
- github
- HTML
- Java
- JavaScript
- Laravel
- Mathematics
- MongoDB
- Mysql
- Node JS
- PHP
- Programming
- Python
- React Js
- Redux
- Rust Programming Language
- SEO
- TypeScript
- Vue JS
- Windows terminal
- Woocommerce
- WordPress
- WordPress Plugin Development