2 Sum – All distinct pairs with given sum (original) (raw)
Given an array arr[] and an integer**target**, We need to find all **distinct pairs in the array such that their sum equals target.
**Examples:
**Input: arr[] = [1, 5, 7, -1, 5], target= 6
**Output: [[1, 5], [-1, 7]]
**Explanation: There are only two pairs that add up to 6: [1, 5]and [-1, 7].**Input: arr[] = [1, 9, -1, 8, 6], target = 4
**Output: []
**Explanation: No pairs add up to 4.
Table of Content
- [Naive Approach] Using Three Nested Loops - O(n^3) Time and O(1) Space
- [Better Approach 1] Using Hash Set - O(n^2) Time and O(n) Space
- [Better Approach 2] Using Two Pointers Technique – O(n*logn) Time and O(1) Space
- [Expected Approach] Using Hash Map – O(n) Time and O(n) Space
[Naive Approach] Using Two Nested Loops
A simple approach is to generate all possible pairs using two nested loops and if they add up to **target value, then for each such pair check whether this pair already exists in the result or not.
C++ `
#include #include #include using namespace std; vector<vector> distinctPairs(vector &arr, int target) { vector<vector> res; int n = arr.size(); for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) {
if (arr[i] + arr[j] == target) {
int first = min(arr[i], arr[j]);
int second = max(arr[i], arr[j]);
vector<int> cur = {first, second};
if(find(res.begin(), res.end(), cur) == res.end())
res.push_back(cur);
}
}
}
return res;} int main() { vector arr = {1, 5, 7, -1, 5}; int target = 6; vector<vector> res = distinctPairs(arr, target); for (int i = 0; i < res.size(); i++) cout << res[i][0] << " " << res[i][1] << endl; return 0; }
C
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> void distinctPairs(int arr[], int n, int target) { int res[1000][2]; int res_count = 0; for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { if (arr[i] + arr[j] == target) { int first = arr[i] < arr[j] ? arr[i] : arr[j]; int second = arr[i] > arr[j] ? arr[i] : arr[j]; bool isDistinct = true; for (int k = 0; k < res_count; k++) { if (res[k][0] == first && res[k][1] == second) { isDistinct = false; break; } } if (isDistinct) { res[res_count][0] = first; res[res_count][1] = second; res_count++; } } } }
for (int i = 0; i < res_count; i++) {
printf("%d %d\n", res[i][0], res[i][1]);
}} int main() { int arr[] = {1, 5, 7, -1, 5}; int target = 6; int n = sizeof(arr) / sizeof(arr[0]); distinctPairs(arr, n, target); return 0; }
Java
import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Collections;
class GfG { static List<List> distinctPairs(int[] arr, int target) { List<List> res = new ArrayList<>(); int n = arr.length; for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { if (arr[i] + arr[j] == target) { int first = Math.min(arr[i], arr[j]); int second = Math.max(arr[i], arr[j]); List cur = new ArrayList<> (Arrays.asList(first, second));
if (!res.contains(cur))
res.add(cur);
}
}
}
return res;
}
public static void main(String[] args) {
int[] arr = {1, 5, 7, -1, 5};
int target = 6;
List<List<Integer>> res = distinctPairs(arr, target);
for (List<Integer> pair : res)
System.out.println(pair.get(0) + " " + pair.get(1));
}}
Python
def distinctPairs(arr, target): res = [] n = len(arr) # Iterating over all possible pairs for i in range(n): for j in range(i + 1, n): if arr[i] + arr[j] == target: cur = [min(arr[i], arr[j]), max(arr[i], arr[j])]
if cur not in res:
res.append(cur)
return resif name == "main": arr = [1, 5, 7, -1, 5] target = 6 res = distinctPairs(arr, target)
for pair in res:
print(pair[0], pair[1])C#
using System; using System.Collections.Generic;
class GfG { static List<List> distinctPairs(int[] arr, int target) { List<List> res = new List<List>(); int n = arr.Length;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (arr[i] + arr[j] == target) {
int first = Math.Min(arr[i], arr[j]);
int second = Math.Max(arr[i], arr[j]);
List<int> cur = new List<int> { first, second };
if (!res.Exists(x => x[0] == cur[0] && x[1] == cur[1]))
res.Add(cur);
}
}
}
return res;
}
static void Main() {
int[] arr = { 1, 5, 7, -1, 5 };
int target = 6;
List<List<int>> res = distinctPairs(arr, target);
foreach (var pair in res)
Console.WriteLine($"{pair[0]} {pair[1]}");
}}
JavaScript
function distinctPairs(arr, target) { let res = []; let n = arr.length; for (let i = 0; i < n; i++) { for (let j = i + 1; j < n; j++) { if (arr[i] + arr[j] === target) { let first = Math.min(arr[i], arr[j]); let second = Math.max(arr[i], arr[j]); let cur = [first, second]; if (!res.some(pair => pair[0] === cur[0] && pair[1] === cur[1])) { res.push(cur); } } } }
return res;} let arr = [1, 5, 7, -1, 5]; let target = 6; let res = distinctPairs(arr, target);
for (let i = 0; i < res.length; i++) console.log(res[i][0] + " " + res[i][1]);
`
**Time Complexity: O(n^3), two nested loops generate all pairs (**O(n²)), and for each pair, find() scans the result vector in **O(n).
**Auxiliary Space: O(1),
[Better Approach 1] Using Hash Set - O(n^2* log n) Time and O(n) Space
A better approach is to generate all possible pairs using two nested loops, check if their sum equals the target, and store them in a hash set to automatically eliminate duplicate pairs.
C++ `
#include
#include
using namespace std;
vector<vector> distinctPairs(vector &arr, int target) {
vector<vector> res;
int n = arr.size();
set<vector> st;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (arr[i] + arr[j] == target) {
int first = min(arr[i], arr[j]);
int second = max(arr[i], arr[j]);
vector cur = {first, second};
// If the pair is not already in the set, add it
if (st.find(cur) == st.end()) {
res.push_back(cur);
st.insert(cur);
}
}
}
}
return res;
}
int main() {
vector arr = {1, 5, 7, -1, 5};
int target = 6;
vector<vector> res = distinctPairs(arr, target);
for (int i = 0; i < res.size(); i++)
cout << res[i][0] << " " << res[i][1] << endl;
return 0;
}
Java
import java.util.*;
class GfG {
static List<List<Integer>> distinctPairs(int[] arr, int target) {
List<List<Integer>> res = new ArrayList<>();
int n = arr.length;
// Set to handle duplicates using sorted pairs
Set<List<Integer>> st = new HashSet<>();
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (arr[i] + arr[j] == target) {
int first = Math.min(arr[i], arr[j]);
int second = Math.max(arr[i], arr[j]);
List<Integer> cur = new ArrayList<>
(Arrays.asList(first, second));
if (!st.contains(cur)) {
res.add(cur);
st.add(cur);
}
}
}
}
return res;
}
public static void main(String[] args) {
int[] arr = {1, 5, 7, -1, 5};
int target = 6;
List<List<Integer>> res = distinctPairs(arr, target);
for (List<Integer> pair : res) {
System.out.println(pair.get(0) + " " + pair.get(1));
}
}}
Python
def distinctPairs(arr, target): res = [] n = len(arr) # Iterating over all possible pairs for i in range(n): for j in range(i + 1, n): if arr[i] + arr[j] == target: cur = [min(arr[i], arr[j]), max(arr[i], arr[j])]
if cur not in res:
res.append(cur)
return resif name == "main": arr = [1, 5, 7, -1, 5] target = 6 res = distinctPairs(arr, target)
for pair in res:
print(pair[0], pair[1])C#
using System; using System.Collections.Generic;
class GfG {
static List<List<int>> distinctPairs(int[] arr, int target) {
List<List<int>> res = new List<List<int>>();
int n = arr.Length;
// Set to handle duplicates using sorted pairs
HashSet<(int, int)> st = new HashSet<(int, int)>();
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (arr[i] + arr[j] == target) {
int first = Math.Min(arr[i], arr[j]);
int second = Math.Max(arr[i], arr[j]);
var cur = (first, second);
if (!st.Contains(cur)) {
res.Add(new List<int> { first, second });
st.Add(cur);
}
}
}
}
return res;
}
static void Main() {
int[] arr = { 1, 5, 7, -1, 5 };
int target = 6;
List<List<int>> res = distinctPairs(arr, target);
foreach (var pair in res) {
Console.WriteLine(pair[0] + " " + pair[1]);
}
}}
JavaScript
function distinctPairs(arr, target) { let res = []; let n = arr.length;
// Set to handle duplicates using sorted pairs
let st = new Set();
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
if (arr[i] + arr[j] === target) {
let first = Math.min(arr[i], arr[j]);
let second = Math.max(arr[i], arr[j]);
let cur = [first, second];
let curString = cur.toString();
if (!st.has(curString)) {
res.push(cur);
st.add(curString);
}
}
}
}
return res;}
let arr = [1, 5, 7, -1, 5]; let target = 6; let res = distinctPairs(arr, target);
res.forEach(pair => console.log(pair[0], pair[1]));
`
**Time Complexity: O(n² * log n).
**Auxiliary Space: O(n), for hash set.
[Expected Approach 1] Using Two Pointers Technique – O(n*logn) Time and O(1) Space
The idea is to sort the array and use two pointers technique to find all the pairs. Initialize **two pointers at the beginning and end of the array. Now, compare the sum of elements at these pointers:
- If **sum = **target, store the pairand skip duplicates to ensure they are **distinct.
- If **sum < **target, we move the **left pointer towards right.
- If **sum > **target, we move the **right pointer towards left.
This continues until all pairs are checked, giving us all the distinct pairs.
C++ `
#include #include
using namespace std; vector<vector> distinctPairs(vector &arr, int target) { vector<vector> res; int n = arr.size(); sort(arr.begin(), arr.end()); int left = 0; int right = n - 1; //iterate until pointers meet while (left < right) { //skip duplicates element on left side if (left > 0 && arr[left] == arr[left - 1]) { left++; continue; } // skip duplicate elements on right side if (right < n - 1 && arr[right] == arr[right + 1]) { right--; continue; } // if pair sum equals target, add to result if (arr[left] + arr[right] == target) { res.push_back({arr[left], arr[right]}); left++; right--; } // if sum is greater than target, move right pointer left else if (arr[left] + arr[right] > target) right--; // if sum is smaller than target, move left pointer right else left++; }
return res;}
int main() { vector arr = {1, 5, 7, -1, 5}; int target = 6;
vector<vector<int>> res = distinctPairs(arr, target);
for (int i = 0; i < res.size(); i++)
cout << res[i][0] << " " << res[i][1] << endl;
return 0;}
C
#include <stdio.h> int compare(const void a, const void b) { return ((int)a - (int)b); }
void distinctPairs(int arr[], int n, int target) { qsort(arr, n, sizeof(int), compare);
int left = 0;
int right = n - 1;
while (left < right) {
if (left > 0 && arr[left] == arr[left - 1]) {
left++;
continue;
}
if (right < n - 1 && arr[right] == arr[right + 1]) {
right--;
continue;
}
// Check if sum equals the target
if (arr[left] + arr[right] == target) {
printf("%d %d\n", arr[left], arr[right]);
left++;
right--;
}
else if (arr[left] + arr[right] > target) {
right--;
}
else {
left++;
}
}}
int main() { int arr[] = {1, 5, 7, -1, 5}; int target = 6; int n = sizeof(arr) / sizeof(arr[0]); distinctPairs(arr, n, target); return 0; }
Java
import java.util.ArrayList; import java.util.Arrays; import java.util.List;
class GfG { static List<List> distinctPairs(int[] arr, int target) { List<List> res = new ArrayList<>();
int l = 0;
int r = arr.length - 1;
while (l < r) {
if (l > 0 && arr[l] == arr[l - 1]) {
l++;
continue;
}
if (r < arr.length - 1 && arr[r] == arr[r + 1]) {
r--;
continue;
}
if (arr[l] + arr[r] == target) {
res.add(Arrays.asList(arr[l], arr[r]));
l++;
r--;
}
else if (arr[l] + arr[r] > target) {
r--;
}
else {
l++;
}
}
return res;
}
public static void main(String[] args) {
int[] arr = {1, 5, 7, -1, 5};
int target = 6;
Arrays.sort(arr);
List<List<Integer>> res = distinctPairs(arr, target);
for (List<Integer> pair : res) {
System.out.println(pair.get(0) + " " + pair.get(1));
}
}}
Python
def distinctPairs(arr, target): res = [] n = len(arr)
arr.sort()
left = 0
right = n - 1
while left < right:
if left > 0 and arr[left] == arr[left - 1]:
left += 1
continue
if right < n - 1 and arr[right] == arr[right + 1]:
right -= 1
continue
if arr[left] + arr[right] == target:
res.append([arr[left], arr[right]])
left += 1
right -= 1
elif arr[left] + arr[right] > target:
right -= 1
else:
left += 1
return resif name == "main": arr = [1, 5, 7, -1, 5] target = 6
res = distinctPairs(arr, target)
for pair in res:
print(pair[0], pair[1])C#
using System; using System.Collections.Generic;
class GfG { static List<List> DistinctPairs(int[] arr, int target) { List<List> res = new List<List>(); int n = arr.Length;
Array.Sort(arr);
int left = 0;
int right = n - 1;
while (left < right) {
if (left > 0 && arr[left] == arr[left - 1]) {
left++;
continue;
}
if (right < n - 1 && arr[right] == arr[right + 1]) {
right--;
continue;
}
if (arr[left] + arr[right] == target) {
res.Add(new List<int> { arr[left], arr[right] });
left++;
right--;
}
else if (arr[left] + arr[right] > target)
right--;
else
left++;
}
return res;
}
static void Main() {
int[] arr = { 1, 5, 7, -1, 5 };
int target = 6;
List<List<int>> res = DistinctPairs(arr, target);
foreach (var pair in res) {
Console.WriteLine(pair[0] + " " + pair[1]);
}
}}
JavaScript
function distinctPairs(arr, target) { let res = []; let n = arr.length; arr.sort((a, b) => a - b);
let left = 0;
let right = n - 1;
while (left < right) {
if (left > 0 && arr[left] === arr[left - 1]) {
left++;
continue;
}
if (right < n - 1 && arr[right] === arr[right + 1]) {
right--;
continue;
}
if (arr[left] + arr[right] === target) {
res.push([arr[left], arr[right]]);
left++;
right--;
}
else if (arr[left] + arr[right] > target)
right--;
else
left++;
}
return res;}
const arr = [1, 5, 7, -1, 5]; const target = 6;
const res = distinctPairs(arr, target); for (let i = 0; i < res.length; i++) console.log(res[i][0] + " " + res[i][1]);
`
**Time Complexity: O(n*log(n)), for sorting the array
**Auxiliary Space: O(1)
**[Expected Approach 2] Using Hash Map – O(n) Time and O(n) Space
The idea is to maintain a hash map to track how many times each element has occurred in the array so far. Traverse all the elements and for each element **arr[i], check if the **complement (target – arr[i]) already exists in the map, if it exists then we have found a pair whose sum is equal to target.
**To avoid including duplicate pairs, we handle two cases:
**When arr[i] == complement :
- We check if
arr[i]has appeared **exactly once before indexi. - If it has, then
arr[i]can pair with itself to form a valid pair with sum = target. - If it has appeared more than once, the pair has already been counted earlier, so this occurrence would create a duplicate and should be ignored.
**When arr[i] != complement :
- We check that the
complementhas appeared **at least once before indexi. - At the same time,
arr[i]should not have appeared before indexi. - If both conditions hold, then
(arr[i], complement)forms a unique pair with sum = target. C++ `
#include #include #include using namespace std;
vector<vector> distinctPairs(vector &arr, int target) { vector<vector> res; int n = arr.size(); unordered_map<int, int> freq;
for (int i = 0; i < n; i++) {
int complement = target - arr[i];
if (complement == arr[i]) {
// If we have already seen this number exactly once before,
// then this is the first valid duplicate pair (arr[i], arr[i])
if (freq[complement] == 1)
res.push_back({arr[i], arr[i]});
}
//complement must exist before and current number should not be processed before
else if (freq[complement] > 0 && freq[arr[i]] == 0) {
res.push_back({min(arr[i], complement), max(arr[i], complement)});
}
freq[arr[i]]++;
}
return res;} int main() { vector arr = {1, 5, 7, -1, 5}; int target = 6; vector<vector> res = distinctPairs(arr, target); for (vector &pair : res) cout << pair[0] << " " << pair[1] << endl;
return 0;}
Java
import java.util.*; class GfG { static List<List> distinctPairs(int[] arr, int target) { List<List> res = new ArrayList<>(); int n = arr.length;
Map<Integer, Integer> freq = new HashMap<>();
for (int i = 0; i < n; i++) {
int complement = target - arr[i];
if (complement == arr[i]) {
if (freq.getOrDefault(complement, 0) == 1)
res.add(Arrays.asList(arr[i], arr[i]));
}
// if complement is not equal to arr[i], then there should
// be at least one occurrence of complement and no occurrence
// of current element in the hash map
else if (freq.getOrDefault(complement, 0) > 0
&& freq.getOrDefault(arr[i], 0) == 0) {
int first = Math.min(arr[i], complement);
int second = Math.max(arr[i], complement);
res.add(Arrays.asList(first, second));
}
freq.put(arr[i], freq.getOrDefault(arr[i], 0) + 1);
}
return res;
}
public static void main(String[] args) {
int[] arr = {1, 5, 7, -1, 5};
int target = 6;
List<List<Integer>> res = distinctPairs(arr, target);
for (List<Integer> pair : res) {
System.out.println(pair.get(0) + " " + pair.get(1));
}
}}
Python
def distinctPairs(arr, target): res = [] n = len(arr)
# frequency map to store the frequency of all elements
freq = {}
for i in range(n):
complement = target - arr[i]
# If the complement is equal to arr[i], then there should
# be only one occurrence of complement in the hash map
if complement == arr[i]:
if freq.get(complement, 0) == 1:
res.append([arr[i], arr[i]])
# if complement is not equal to arr[i], then there should
# be at least one occurrence of complement and no occurrence
# of current element in the hash map
elif freq.get(complement, 0) > 0 and freq.get(arr[i], 0) == 0:
first = min(arr[i], complement)
second = max(arr[i], complement)
res.append([first, second])
freq[arr[i]] = freq.get(arr[i], 0) + 1
return resif name == "main": arr = [1, 5, 7, -1, 5] target = 6
res = distinctPairs(arr, target)
for pair in res:
print(pair[0], pair[1])C#
using System; using System.Collections.Generic;
class GfG { static List<List> distinctPairs(List arr, int target) { List<List> res = new List<List>(); int n = arr.Count;
Dictionary<int, int> freq = new Dictionary<int, int>();
for (int i = 0; i < n; i++) {
int complement = target - arr[i];
// If the complement is equal to arr[i], then there should
// be only one occurrence of complement in the hash map
if (complement == arr[i]) {
if (freq.GetValueOrDefault(complement, 0) == 1)
res.Add(new List<int> { arr[i], arr[i] });
}
// if complement is not equal to arr[i], then there should
// be at least one occurrence of complement and no occurrence
// of current element in the hash map
else if (freq.GetValueOrDefault(complement, 0) > 0
&& freq.GetValueOrDefault(arr[i], 0) == 0) {
int first = Math.Min(arr[i], complement);
int second = Math.Max(arr[i], complement);
res.Add(new List<int> { first, second });
}
freq[arr[i]] = freq.GetValueOrDefault(arr[i], 0) + 1;
}
return res;
}
static void Main(string[] args) {
List<int> arr = new List<int> { 1, 5, 7, -1, 5 };
int target = 6;
List<List<int>> res = distinctPairs(arr, target);
foreach (var pair in res)
Console.WriteLine($"{pair[0]} {pair[1]}");
}}
JavaScript
function distinctPairs(arr, target) { let res = []; let n = arr.length;
let freq = new Map();
for (let i = 0; i < n; i++) {
let complement = target - arr[i];
// If the complement is equal to arr[i], then there should
// be only one occurrence of complement in the hash map
if (complement === arr[i]) {
if (freq.get(complement) === 1)
res.push([arr[i], arr[i]]);
}
// if complement is not equal to arr[i], then there should
// be at least one occurrence of complement and no occurrence
// of current element in the hash map
else if (freq.get(complement) > 0 && freq.get(arr[i]) === undefined) {
let first = Math.min(arr[i], complement);
let second = Math.max(arr[i], complement);
res.push([first, second]);
}
freq.set(arr[i], (freq.get(arr[i]) || 0) + 1);
}
return res;}
const arr = [1, 5, 7, -1, 5]; const target = 6;
const res = distinctPairs(arr, target); for (const pair of res) { console.log(pair[0], pair[1]); }
`
**Time Complexity: O(n)
**Auxiliary Space: O(n)
****Note:**In the rare case of severe hash collisions in the unordered_map, operations degrade to O(n), making the overall complexity **O(n²).