Given an array arr[] and an integer target, the task is to find all possible indices {i, j, k} of triplet {arr[i], arr[j], arr[k]} such that their sum is equal to given target and all indices in a triplet should be distinct (i != j, j != k, k != i). We need to return indices of a triplet in sorted order, i.e., i < j < k.
Examples:
Input: arr[] = {0, -1, 2, -3, 1}, target = -2
Output: {{0, 3, 4}, {1, 2, 3}}
Explanation: Two triplets that add up to -2 are:
arr[0] + arr[3] + arr[4] = 0 + (-3) + (1) = -2
arr[1] + arr[2] + arr[3] = (-1) + 2 + (-3) = -2
Input: arr[] = {1, -2, 1, 0, 5}, target = 1
Output: {}
Explanation: There is no triplet whose sum is equal to 1.
Table of Content
[Naive Approach] Explore all Triplets - O(n^3) Time and O(1) Space
The naive approach is to explore all the triplets using three nested loops and if the sum of any triplet is equal to given target then add it to the result.
// C++ program to find all triplets having sum equal to
// target by exploring all possible triplets
#include <iostream>
#include <vector>
using namespace std;
vector<vector<int>> findTriplets(vector<int> &arr, int target) {
vector<vector<int>> res;
int n = arr.size();
// Generating all triplets
for (int i = 0; i < n - 2; i++) {
for (int j = i + 1; j < n - 1; j++) {
for (int k = j + 1; k < n; k++) {
// If the sum of a triplet is equal to target
// then add it's indices to the result
if (arr[i] + arr[j] + arr[k] == target)
res.push_back({i, j, k});
}
}
}
return res;
}
int main() {
vector<int> arr = {0, -1, 2, -3, 1};
int target = -2;
vector<vector<int>> ans = findTriplets(arr, target);
for (int i = 0; i < ans.size(); i++)
cout << ans[i][0] << " " << ans[i][1] << " " <<
ans[i][2] << endl;
return 0;
}
// C program to find all triplets having sum equal to
// target by exploring all possible triplets
#include <stdio.h>
void findTriplets(int *arr, int n, int target) {
// Generating all triplets
for (int i = 0; i < n - 2; i++) {
for (int j = i + 1; j < n - 1; j++) {
for (int k = j + 1; k < n; k++) {
// If the sum of a triplet is equal to target
if (arr[i] + arr[j] + arr[k] == target) {
printf("%d %d %d\n", i, j, k);
}
}
}
}
}
int main() {
int arr[] = {0, -1, 2, -3, 1};
int target = -2;
findTriplets(arr, sizeof(arr) / sizeof(arr[0]), target);
return 0;
}
// Java program to find all triplets having sum equal to
// target by exploring all possible triplets
import java.util.ArrayList;
import java.util.List;
class GfG {
static List<List<Integer>> findTriplets(int[] arr, int target) {
List<List<Integer>> res = new ArrayList<>();
int n = arr.length;
// Generating all triplets
for (int i = 0; i < n - 2; i++) {
for (int j = i + 1; j < n - 1; j++) {
for (int k = j + 1; k < n; k++) {
// If the sum of triplet is equal to target
// then add it's indices to the result
if (arr[i] + arr[j] + arr[k] == target) {
List<Integer> triplet = new ArrayList<>();
triplet.add(i);
triplet.add(j);
triplet.add(k);
res.add(triplet);
}
}
}
}
return res;
}
public static void main(String[] args) {
int[] arr = {0, -1, 2, -3, 1};
int target = -2;
List<List<Integer>> ans = findTriplets(arr, target);
for (List<Integer> triplet : ans)
System.out.println(triplet.get(0) + " " +
triplet.get(1) + " " + triplet.get(2));
}
}
# Python program to find all triplets having sum equal to
# target by exploring all possible triplets
def findTriplets(arr, target):
res = []
n = len(arr)
# Generating all triplets
for i in range(n - 2):
for j in range(i + 1, n - 1):
for k in range(j + 1, n):
# If the sum of triplet is equal to target
# then add it's indices to the result
if arr[i] + arr[j] + arr[k] == target:
res.append([i, j, k])
return res
arr = [0, -1, 2, -3, 1]
target = -2
ans = findTriplets(arr, target)
for triplet in ans:
print(triplet[0], triplet[1], triplet[2])
// C# program to find all triplets having sum equal to
// target by exploring all possible triplets
using System;
using System.Collections.Generic;
class GfG {
static List<List<int>> FindTriplets(int[] arr, int target) {
List<List<int>> res = new List<List<int>>();
int n = arr.Length;
// Generating all triplets
for (int i = 0; i < n - 2; i++) {
for (int j = i + 1; j < n - 1; j++) {
for (int k = j + 1; k < n; k++) {
// If the sum of triplet is equal to target
// then add it's indices to the result
if (arr[i] + arr[j] + arr[k] == target) {
res.Add(new List<int> { i, j, k });
}
}
}
}
return res;
}
public static void Main() {
int[] arr = { 0, -1, 2, -3, 1 };
int target = -2;
List<List<int>> ans = FindTriplets(arr, target);
foreach (var triplet in ans) {
Console.WriteLine($"{triplet[0]} {triplet[1]} {triplet[2]}");
}
}
}
// JavaScript program to find all triplets having sum equal to
// target by exploring all possible triplets
function findTriplets(arr, target) {
const res = [];
const n = arr.length;
// Generating all triplets
for (let i = 0; i < n - 2; i++) {
for (let j = i + 1; j < n - 1; j++) {
for (let k = j + 1; k < n; k++) {
// If the sum of triplet is equal to target
// then add it's indices to the result
if (arr[i] + arr[j] + arr[k] === target) {
res.push([i, j, k]);
}
}
}
}
return res;
}
const arr = [0, -1, 2, -3, 1];
const target = -2;
const ans = findTriplets(arr, target);
ans.forEach(triplet => {
console.log(triplet[0] + " " + triplet[1] + " " + triplet[2]);
});
Output
0 3 4 1 2 3
[Expected Approach] Using Hashing – O(n^3) time and O(n^2) space
The idea is to store sum of all the pairs with their indices in the hash map or dictionary. Then, for each element in the array, we check if the pair which makes triplet's sum zero, exists in the hash map or not. Since there can be multiple valid pairs, we add each one to the hash set (to manage duplicates) while ensuring that all indices in the triplet are distinct.
In the worst case, this approach also has O(n^3) Time Complexity but in the average case, it is much faster than the Naive Approach as we are iterating over only those triplets whose sum is equal to target.
// C++ program to find triplets having sum equal to
// target using hashing
#include <iostream>
#include <vector>
#include <set>
#include <unordered_map>
#include <algorithm>
using namespace std;
vector<vector<int>> findTriplets(vector<int> &arr, int target) {
// Ideally we should use an unordered_set here, but C++
// does not support vector as a key in an unordered_set
// So we have used set to keep the code simple. However
// set internally uses Red Black Tree and has O(Log n)
// time complexities for operations
set<vector<int>> resSet;
int n = arr.size();
unordered_map<int, vector<pair<int, int>>> mp;
// Store sum of all the pairs with their indices
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++)
mp[arr[i] + arr[j]].push_back({i, j});
}
for (int i = 0; i < n; i++) {
// Find remaining value to get sum equal to target
int rem = target - arr[i];
if (mp.find(rem) != mp.end()) {
vector<pair<int, int>> pairs = mp[rem];
for (auto p : pairs) {
// Ensure no two indices are same in triplet
if (p.first != i && p.second != i) {
vector<int> curr = {i, p.first, p.second};
sort(curr.begin(), curr.end());
resSet.insert(curr);
}
}
}
}
vector<vector<int>> res(resSet.begin(), resSet.end());
return res;
}
int main() {
vector<int> arr = {0, -1, 2, -3, 1};
int target = -2;
vector<vector<int>> ans = findTriplets(arr, target);
for (int i = 0; i < ans.size(); i++)
cout << ans[i][0] << " " << ans[i][1] << " " <<
ans[i][2] << endl;
return 0;
}
// Java program to find triplets having sum equal to
// target using hashing
import java.util.*;
class GfG {
static List<List<Integer>> findTriplets(int[] arr, int target) {
// Set to handle duplicates
Set<List<Integer>> resSet = new HashSet<>();
int n = arr.length;
Map<Integer, List<int[]>> mp = new HashMap<>();
// Store sum of all the pairs with their indices
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
mp.computeIfAbsent(arr[i] + arr[j],
k -> new ArrayList<>()).add(new int[]{i, j});
}
}
for (int i = 0; i < n; i++) {
// Find remaining value to get sum equal to target
int rem = target - arr[i];
if (mp.containsKey(rem)) {
List<int[]> pairs = mp.get(rem);
for (int[] p : pairs) {
// Ensure no two indices are same in triplet
if (p[0] != i && p[1] != i) {
List<Integer> curr = Arrays.asList(i, p[0], p[1]);
Collections.sort(curr);
resSet.add(curr);
}
}
}
}
return new ArrayList<>(resSet);
}
public static void main(String[] args) {
int[] arr = {0, -1, 2, -3, 1};
int target = -2;
List<List<Integer>> ans = findTriplets(arr, target);
for (List<Integer> triplet : ans) {
System.out.println(triplet.get(0) + " " +
triplet.get(1) + " " + triplet.get(2));
}
}
}
# Python program to find triplets having sum equal to
# target using hashing
def findTriplets(arr, target):
# Set to handle duplicates
resSet = set()
n = len(arr)
mp = {}
# Store sum of all the pairs with their indices
for i in range(n):
for j in range(i + 1, n):
s = arr[i] + arr[j]
if s not in mp:
mp[s] = []
mp[s].append((i, j))
for i in range(n):
# Find remaining value to get sum equal to target
rem = target - arr[i]
if rem in mp:
for p in mp[rem]:
# Ensure no two indices are the same in the triplet
if p[0] != i and p[1] != i:
curr = sorted([i, p[0], p[1]])
resSet.add(tuple(curr))
return [list(triplet) for triplet in resSet]
if __name__ == "__main__":
arr = [0, -1, 2, -3, 1]
target = -2
ans = findTriplets(arr, target)
for triplet in ans:
print(triplet[0], triplet[1], triplet[2])
// C# program to find triplets having sum equal to
// target using hashing
using System;
using System.Collections.Generic;
using System.Linq;
class GfG {
static List<List<int> > FindTriplets(int[] arr,
int target) {
// Set to handle duplicates
HashSet<List<int> > resSet
= new HashSet<List<int> >(new ListComparer());
int n = arr.Length;
Dictionary<int, List<Tuple<int, int> > > mp
= new Dictionary<int,
List<Tuple<int, int> > >();
// Store sum of all the pairs with their indices
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
int sum = arr[i] + arr[j];
if (!mp.ContainsKey(sum)) {
mp[sum] = new List<Tuple<int, int> >();
}
mp[sum].Add(new Tuple<int, int>(i, j));
}
}
for (int i = 0; i < n; i++) {
// Find remaining value to get sum equal to target
int rem = target - arr[i];
if (mp.ContainsKey(rem)) {
List<Tuple<int, int> > pairs = mp[rem];
foreach(var p in pairs)
{
// Ensure no two indices are the same in
// the triplet
if (p.Item1 != i && p.Item2 != i) {
List<int> curr
= new List<int>{ i, p.Item1,
p.Item2 };
curr.Sort();
resSet.Add(curr);
}
}
}
}
return new List<List<int> >(resSet);
}
static void Main() {
int[] arr = { 0, -1, 2, -3, 1 };
int target = -2;
List<List<int> > ans = FindTriplets(arr, target);
foreach(var triplet in ans)
Console.WriteLine($"{triplet[0]} {triplet[1]} {triplet[2]}");
}
class ListComparer : IEqualityComparer<List<int> > {
public bool Equals(List<int> x, List<int> y) {
return x.SequenceEqual<int>(y);
}
public int GetHashCode(List<int> obj) {
return string.Join(",", obj).GetHashCode();
}
}
}
// JavaScript program to find triplets having sum equal to
// target using hashing
function findTriplets(arr, target) {
// Set to handle duplicates
let resSet = new Set();
let n = arr.length;
let mp = new Map();
// Store sum of all the pairs with their indices
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
let sum = arr[i] + arr[j];
if (!mp.has(sum)) {
mp.set(sum, []);
}
mp.get(sum).push([i, j]);
}
}
for (let i = 0; i < n; i++) {
// Find remaining value to get sum equal to target
let rem = target - arr[i];
if (mp.has(rem)) {
let pairs = mp.get(rem);
for (let p of pairs) {
// Ensure no two indices are the same in the triplet
if (p[0] != i && p[1] != i) {
let curr = [i, p[0], p[1]].sort((a, b) => a - b);
resSet.add(curr.join(","));
}
}
}
}
return Array.from(resSet).map(triplet => triplet.split(",").map(Number));
}
const arr = [0, -1, 2, -3, 1];
const target = -2;
const ans = findTriplets(arr, target);
ans.forEach(triplet => {
console.log(`${triplet[0]} ${triplet[1]} ${triplet[2]}`);
});
Output
0 3 4 1 2 3