Given an array arr[] and a target value, the task is to find all possible indices (i, j) of pairs (arr[i], arr[j]) whose sum is equal to target and i != j. We can return pairs in any order, but all the returned pairs should be internally sorted, that is for any pair(i, j), i should be less than j.
Examples:
Input: arr[] = {10, 20, 30, 20, 10, 30}, target = 50
Output: {{1, 2}, {1, 5}, {2, 3}, {3, 5}}
Explanation: All pairs with sum = 50 are:
- arr[1] + arr[2] = 20 + 30 = 50
- arr[1] + arr[5] = 20 + 30 = 50
- arr[2] + arr[3] = 30 + 20 = 50
- arr[3] + arr[5] = 20 + 30 = 50
Input: arr[] = {10, 20, 30, 20, 10, 30}, target = 80
Output: { }
Explanation: No pairs have sum = 80.
Table of Content
[Naive Approach] Using Nested Loops - O(n^2) Time and O(1) Space
The simplest approach is to generate all possible pairs from the given array arr[] and if the sum of elements of the pairs is equal to target, then add it to the result.
// C++ Code to find all pairs using nested loops
#include <iostream>
#include <vector>
using namespace std;
// function to find all pairs
vector<vector<int>> findAllPairs(vector<int> &arr, int target) {
int n = arr.size();
vector<vector<int>> res;
// Two nested loops to generate all pairs
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
// If sum of pair equals target, add it to result
if(arr[i] + arr[j] == target) {
res.push_back({i, j});
}
}
}
return res;
}
int main() {
vector<int> arr = {10, 20, 30, 20, 10, 30};
int target = 50;
vector<vector<int>> res = findAllPairs(arr, target);
for(auto pair: res) {
cout << pair[0] << " " << pair[1] << "\n";
}
return 0;
}
// C Code to find all pairs using nested loops
#include <stdio.h>
// function to find all pairs
void findAllPairs(int *arr, int n, int target) {
// Two nested loops to generate all pairs
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
// If sum of pair equals target, print it
if (arr[i] + arr[j] == target) {
printf("%d %d\n", i, j);
}
}
}
}
int main() {
int arr[] = {10, 20, 30, 20, 10, 30};
int target = 50;
int n = sizeof(arr) / sizeof(arr[0]);
findAllPairs(arr, n, target);
return 0;
}
// Java Code to find all pairs using nested loops
import java.util.ArrayList;
import java.util.List;
class GfG {
// function to find all pairs
static List<List<Integer>> findAllPairs(int[] arr, int target) {
int n = arr.length;
List<List<Integer>> res = new ArrayList<>();
// Two nested loops to generate all pairs
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
// If sum of pair equals target, add it to result
if(arr[i] + arr[j] == target) {
List<Integer> pair = new ArrayList<>();
pair.add(i);
pair.add(j);
res.add(pair);
}
}
}
return res;
}
public static void main(String[] args) {
int[] arr = {10, 20, 30, 20, 10, 30};
int target = 50;
List<List<Integer>> res = findAllPairs(arr, target);
for(List<Integer> pair: res) {
System.out.println(pair.get(0) + " " + pair.get(1));
}
}
}
# Python Code to find all pairs using nested loops
def findAllPairs(arr, target):
n = len(arr)
res = []
# Two nested loops to generate all pairs
for i in range(n):
for j in range(i + 1, n):
# If sum of pair equals target, add it to result
if arr[i] + arr[j] == target:
res.append([i, j])
return res
if __name__ == "__main__":
arr = [10, 20, 30, 20, 10, 30]
target = 50
res = findAllPairs(arr, target)
for pair in res:
print(pair[0], pair[1])
// C# Code to find all pairs using nested loops
using System;
using System.Collections.Generic;
class GfG {
// function to find all pairs
static List<List<int>> findAllPairs(List<int> arr, int target) {
int n = arr.Count;
List<List<int>> res = new List<List<int>>();
// Two nested loops to generate all pairs
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
// If sum of pair equals target, add it to result
if (arr[i] + arr[j] == target) {
res.Add(new List<int> { i, j });
}
}
}
return res;
}
static void Main(string[] args) {
List<int> arr = new List<int> { 10, 20, 30, 20, 10, 30 };
int target = 50;
List<List<int>> res = findAllPairs(arr, target);
foreach (var pair in res) {
Console.WriteLine(pair[0] + " " + pair[1]);
}
}
}
// JavaScript Code to find all pairs using nested loops
// function to find all pairs
function findAllPairs(arr, target) {
let n = arr.length;
let res = [];
// Two nested loops to generate all pairs
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
// If sum of pair equals target, add it to result
if (arr[i] + arr[j] === target) {
res.push([i, j]);
}
}
}
return res;
}
const arr = [10, 20, 30, 20, 10, 30];
const target = 50;
const res = findAllPairs(arr, target);
for (const pair of res) {
console.log(pair[0] + " " + pair[1]);
}
Output
1 2 1 5 2 3 3 5
[Expected Approach] Using Hashing - O(n^2) Time and O(n) Space
The idea is to maintain a hash map with element as key and its indices as values. Iterate over the array and for each element arr[i], if (target - arr[i]) exists in the hash map, then pair i with all indices of (target - arr[i]) and store them in result.
In the worst case, this approach also takes O(n^2) time but in the average case, it is much faster than Naive approach as we are iterating over only those pairs whose sum is equal to target.
// C++ Code to find all pairs using hashing
#include <iostream>
#include <unordered_map>
#include <vector>
using namespace std;
// function to find all pairs
vector<vector<int>> findAllPairs(vector<int> &arr, int target)
{
int n = arr.size();
// buckets[i] stores all j (j > i) such that
// arr[i] + arr[j] = target
// filled in increasing order of j automatically,
// since we scan left to right
vector<vector<int>> buckets(n);
// maps a value to the list of indices where
// it has occurred so far
unordered_map<int, vector<int>> mp;
mp.reserve(n);
for (int i = 0; i < n; i++)
{
int need = target - arr[i];
// if a smaller index with the complementary
// value exists, pair it with i
if (mp.find(need) != mp.end())
{
for (int idx : mp[need])
buckets[idx].push_back(i);
}
mp[arr[i]].push_back(i);
}
// flatten buckets in order 0..n-1; result is
// already lexicographically sorted, since bucket
// index is the first element and each bucket's
// contents are appended in increasing order of
// the second element
vector<vector<int>> res;
for (int i = 0; i < n; i++)
{
for (int j : buckets[i])
res.push_back({i, j});
}
return res;
}
int main()
{
vector<int> arr = {10, 20, 30, 20, 10, 30};
int target = 50;
vector<vector<int>> res = findAllPairs(arr, target);
for (auto pair : res)
{
cout << pair[0] << " " << pair[1] << "\n";
}
return 0;
}
import java.util.*;
class Main {
public static List<List<Integer>> findAllPairs(int[] arr, int target) {
int n = arr.length;
// buckets[i] stores all j (j > i) such that
// arr[i] + arr[j] = target
// filled in increasing order of j automatically,
// since we scan left to right
List<List<List<Integer>>> buckets = new ArrayList<>();
for (int i = 0; i < n; i++) {
buckets.add(new ArrayList<>());
}
// maps a value to the list of indices where
// it has occurred so far
Map<Integer, List<Integer>> mp = new HashMap<>();
for (int i = 0; i < n; i++) {
int need = target - arr[i];
// if a smaller index with the complementary
// value exists, pair it with i
if (mp.containsKey(need)) {
for (int idx : mp.get(need)) {
buckets.get(idx).add(Arrays.asList(idx, i));
}
}
if (!mp.containsKey(arr[i])) {
mp.put(arr[i], new ArrayList<>());
}
mp.get(arr[i]).add(i);
}
// flatten buckets in order 0..n-1; result is
// already lexicographically sorted, since bucket
// index is the first element and each bucket's
// contents are appended in increasing order of
// the second element
List<List<Integer>> res = new ArrayList<>();
for (int i = 0; i < n; i++) {
for (List<Integer> pair : buckets.get(i)) {
res.add(pair);
}
}
return res;
}
public static void main(String[] args) {
int[] arr = {10, 20, 30, 20, 10, 30};
int target = 50;
List<List<Integer>> res = findAllPairs(arr, target);
for (List<Integer> pair : res) {
System.out.println(pair.get(0) + " " + pair.get(1));
}
}
}
def findAllPairs(arr, target):
n = len(arr)
# buckets[i] stores all j (j > i) such that
# arr[i] + arr[j] = target
# filled in increasing order of j automatically,
# since we scan left to right
buckets = [[] for _ in range(n)]
# maps a value to the list of indices where
# it has occurred so far
mp = {}
for i in range(n):
need = target - arr[i]
# if a smaller index with the complementary
# value exists, pair it with i
if need in mp:
for idx in mp[need]:
buckets[idx].append((idx, i))
if arr[i] not in mp:
mp[arr[i]] = []
mp[arr[i]].append(i)
# flatten buckets in order 0..n-1; result is
# already lexicographically sorted, since bucket
# index is the first element and each bucket's
# contents are appended in increasing order of
# the second element
res = []
for i in range(n):
for pair in buckets[i]:
res.append(pair)
return res
if __name__ == '__main__':
arr = [10, 20, 30, 20, 10, 30]
target = 50
res = findAllPairs(arr, target)
for pair in res:
print(pair[0], pair[1])
using System;
using System.Collections.Generic;
class Program
{
// function to find all pairs
public static List<List<int>> findAllPairs(int[] arr, int target)
{
int n = arr.Length;
// buckets[i] stores all j (j > i) such that
// arr[i] + arr[j] = target
// filled in increasing order of j automatically,
// since we scan left to right
List<List<int>> buckets = new List<List<int>>();
for (int i = 0; i < n; i++) {
buckets.Add(new List<int>(2));
}
// maps a value to the list of indices where
// it has occurred so far
Dictionary<int, List<int>> mp = new Dictionary<int, List<int>>();
for (int i = 0; i < n; i++)
{
int need = target - arr[i];
// if a smaller index with the complementary
// value exists, pair it with i
if (mp.ContainsKey(need))
{
foreach (int idx in mp[need])
{
buckets[idx].Add(i);
}
}
if (!mp.ContainsKey(arr[i]))
{
mp[arr[i]] = new List<int>();
}
mp[arr[i]].Add(i);
}
// flatten buckets in order 0..n-1; result is
// already lexicographically sorted, since bucket
// index is the first element and each bucket's
// contents are appended in increasing order of
// the second element
List<List<int>> res = new List<List<int>>();
for (int i = 0; i < n; i++)
{
foreach (int pair in buckets[i])
{
res.Add(new List<int>{i, pair});
}
}
return res;
}
static void Main(string[] args)
{
int[] arr = { 10, 20, 30, 20, 10, 30 };
int target = 50;
List<List<int>> res = findAllPairs(arr, target);
foreach (var pair in res)
{
Console.WriteLine(pair[0] + " " + pair[1]);
}
}
}
function findAllPairs(arr, target) {
const n = arr.length;
// buckets[i] stores all j (j > i) such that
// arr[i] + arr[j] = target
// filled in increasing order of j automatically,
// since we scan left to right
const buckets = Array.from({ length: n }, () => []);
// maps a value to the list of indices where
// it has occurred so far
const mp = new Map();
for (let i = 0; i < n; i++) {
const need = target - arr[i];
// if a smaller index with the complementary
// value exists, pair it with i
if (mp.has(need)) {
for (const idx of mp.get(need)) {
buckets[idx].push([idx, i]);
}
}
if (!mp.has(arr[i])) {
mp.set(arr[i], []);
}
mp.get(arr[i]).push(i);
}
// flatten buckets in order 0..n-1; result is
// already lexicographically sorted, since bucket
// index is the first element and each bucket's
// contents are appended in increasing order of
// the second element
const res = [];
for (let i = 0; i < n; i++) {
for (const pair of buckets[i]) {
res.push(pair);
}
}
return res;
}
const arr = [10, 20, 30, 20, 10, 30];
const target = 50;
const res = findAllPairs(arr, target);
for (const pair of res) {
console.log(pair[0] + ''+ pair[1]);
}
Output
1 2 2 3 1 5 3 5