Given an array arr[], and an integer target, find all possible triplets in the array whose sum is equal to the given target value. We can return triplets in any order, but all the returned triplets should be internally sorted, i.e., for any triplet [q1, q2, q3], the condition q1 ≤ q2 ≤ q3 should hold.
Examples:
Input: arr[] = {0, -1, 2, -3, 1}, target = -2
Output: {{0, -3, 1}, {-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.Input: arr[] =
{1, 1, 1, 1}, target =3
Output:{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}}
Explanation:Four triples that add up to 3 are:
arr[0] + arr[1] + arr[2] = 1 + 1 + 1 = 3
arr[0] + arr[1] + arr[3] = 1 + 1 + 1 = 3
arr[0] + arr[2] + arr[3] = 1 + 1 + 1 = 3
arr[1] + arr[2] + arr[3] = 1 + 1 + 1 = 3
Table of Content
[Naive Approach] Explore all Triplets - O(n3) 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.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<vector<int>> threeSum(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 Sum is equal to target add it to result
if (arr[i] + arr[j] + arr[k] == target){
vector<int> a = {arr[i], arr[j], arr[k]};
sort(a.begin(), a.end());
res.push_back(a);
}
}
}
}
return res;
}
int main() {
vector<int> arr = {0, -1, 2, -3, 1};
int target = -2;
vector<vector<int>> ans = threeSum(arr, target);
for (int i = 0; i < ans.size(); i++)
cout << ans[i][0] << " " << ans[i][1] << " " << ans[i][2] << endl;
return 0;
}
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
import java.util.Arrays;
class GfG {
static List<List<Integer>> threeSum(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 to the result
if (arr[i] + arr[j] + arr[k] == target) {
List<Integer> a = Arrays.asList(arr[i], arr[j], arr[k]);
Collections.sort(a);
res.add(a);
}
}
}
}
return res;
}
public static void main(String[] args) {
int[] arr = {0, -1, 2, -3, 1};
int target = -2;
List<List<Integer>> ans = threeSum(arr, target);
for (List<Integer> triplet : ans)
System.out.println(triplet.get(0) + " " +
triplet.get(1) + " " + triplet.get(2));
}
}
def threeSum(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 to the result
if arr[i] + arr[j] + arr[k] == target:
a = sorted([arr[i], arr[j], arr[k]])
res.append(a)
return res
arr = [0, -1, 2, -3, 1]
target = -2
ans = threeSum(arr, target)
for triplet in ans:
print(triplet[0], triplet[1], triplet[2])
using System;
using System.Collections.Generic;
class GfG {
static List<List<int>> threeSum(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 to the result
if (arr[i] + arr[j] + arr[k] == target) {
List<int> a = new List<int> { arr[i], arr[j], arr[k] };
a.Sort();
res.Add(a);
}
}
}
}
return res;
}
public static void Main() {
int[] arr = { 0, -1, 2, -3, 1 };
int target = -2;
List<List<int>> ans = threeSum(arr, target);
foreach (var triplet in ans) {
Console.WriteLine($"{triplet[0]} {triplet[1]} {triplet[2]}");
}
}
}
function threeSum(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) {
const a = [ arr[i], arr[j], arr[k] ].sort((x, y) => x - y);
res.push(a);
}
}
}
}
return res;
}
// Driver Code
const arr = [0, -1, 2, -3, 1];
const target = -2;
const ans = threeSum(arr, target);
ans.forEach(triplet => {
console.log(triplet[0] + " " + triplet[1] + " " + triplet[2]);
});
Output
-3 0 1 -3 -1 2
[Better Approach] Using Hashing – O(n3) time and O(n) space
Fix one number and use a hashmap while scanning the rest of the array to instantly check if the required third number has already appeared.
In the worst case, this approach also has O(n3) 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.
- Create an empty hashmap to store the frequency of numbers seen so far.
- Fix the first element of the triplet using index i, and reset the hashmap for every new i.
- Traverse the array from i + 1 using index j, treating arr[j] as the second element of the triplet.
- At each j, calculate the third number needed: numberNeeded = target - arr[i] - arr[j].
- Check whether numberNeeded exists in the hashmap. If it does, it means a valid triplet can be formed — add one triplet to the result for every occurrence of numberNeeded recorded so far (this naturally handles duplicates).
- After checking, insert/update arr[j] in the hashmap so future indices can use it as the "needed" number.
- Repeat for all i and j, and return the collected triplets.
Consider the array: arr[] = [0, -1, -1, 1, 2], target = 0
We fix each i one at a time and use a hashmap to track how many times each number has been seen between i+1 and j-1.
i = 0 (arr[i] = 0)
- Hash = { }
- j = 1, arr[j] = -1: numberNeeded = 1. Not in hash. Insert -1. Hash = {-1: 1}
- j = 2, arr[j] = -1: numberNeeded = 1. Not in hash. Insert -1. Hash = {-1: 2}
- j = 3, arr[j] = 1: numberNeeded = -1. Found in hash (count 2) → triplets {0, 1, -1} and {0, 1, -1} added. Insert 1. Hash = {-1: 2, 1: 1}
- j = 4, arr[j] = 2: numberNeeded = -2. Not in hash. Insert 2. Hash = {-1: 2, 1: 1, 2: 1}
Hashmap advantage at j = 3: count of -1 fetched directly in O(1), instead of scanning backward to count it manually.
i = 1 (arr[i] = -1)
- Hash = { }
- j = 2, arr[j] = -1: numberNeeded = 2. Not in hash. Insert -1. Hash = {-1: 1}
- j = 3, arr[j] = 1: numberNeeded = 0. Not in hash. Insert 1. Hash = {-1: 1, 1: 1}
- j = 4, arr[j] = 2: numberNeeded = -1. Found in hash (count 1) → triplet {-1, 2, -1} added. Insert 2. Hash = {-1: 1, 1: 1, 2: 1}
i = 2 (arr[i] = -1)
- Hash = { }
- j = 3, arr[j] = 1: numberNeeded = 0. Not in hash. Insert 1. Hash = {1: 1}
- j = 4, arr[j] = 2: numberNeeded = -1. Not in hash. Insert 2. Hash = {1: 1, 2: 1}
No more valid i remain (only 2 elements left).
Final result: [[-1, 0, 1], [-1, 0, 1], [-1, -1, 2]]
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
vector<vector<int>> threeSum(vector<int>& arr, int target) {
vector<vector<int>> result;
int n = arr.size();
// Fix the first element of the triplet using index i
for (int i = 0; i < n - 2; i++) {
// Stores frequency of each number seen so far between i+1 and j-1
unordered_map<int, int> freqMap;
// j scans forward, acting as the second element of the triplet
for (int j = i + 1; j < n; j++) {
// The third number needed to complete the sum with arr[i] and arr[j]
int numberNeeded = target - arr[i] - arr[j];
// Check if this needed number was already seen earlier
if (freqMap.find(numberNeeded) != freqMap.end()) {
// It may have occurred multiple times, so count all its occurrences
int freqOfNumberNeeded = freqMap[numberNeeded];
// Add one triplet for each past occurrence of the needed number
for (int k = 0; k < freqOfNumberNeeded; k++) {
// Form the triplet from arr[i], arr[j], and the needed number
vector<int> triplet = {arr[i], arr[j], numberNeeded};
// Sort the 3 elements so the triplet has a consistent order
sort(triplet.begin(), triplet.end());
// Add this triplet to the result
result.push_back(triplet);
}
}
// Update the frequency map with the current arr[j]
freqMap[arr[j]]++;
}
}
return result;
}
int main() {
vector<int> arr = {0, -1, 2, -3, 1};
int target = -2;
vector<vector<int>> ans = threeSum(arr, target);
for (int i = 0; i < ans.size(); i++)
cout << ans[i][0] << " " << ans[i][1] << " " << ans[i][2] << endl;
return 0;
}
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Arrays;
import java.util.Collections;
class GfG {
static List<List<Integer>> threeSum(int[] arr, int target) {
List<List<Integer>> result = new ArrayList<>();
int n = arr.length;
// Fix the first element of the triplet using index i
for (int i = 0; i < n - 2; i++) {
// Stores frequency of each number seen so far between i+1 and j-1
Map<Integer, Integer> freqMap = new HashMap<>();
// j scans forward, acting as the second element of the triplet
for (int j = i + 1; j < n; j++) {
// The third number needed to complete the sum with arr[i] and arr[j]
int numberNeeded = target - arr[i] - arr[j];
// Check if this needed number was already seen earlier
if (freqMap.containsKey(numberNeeded)) {
// It may have occurred multiple times, so count all its occurrences
int freqOfNumberNeeded = freqMap.get(numberNeeded);
// Add one triplet for each past occurrence of the needed number
for (int k = 0; k < freqOfNumberNeeded; k++) {
// Form the triplet from arr[i], arr[j], and the needed number
List<Integer> triplet = Arrays.asList(arr[i], arr[j], numberNeeded);
// Sort the 3 elements so the triplet has a consistent order
Collections.sort(triplet);
// Add this triplet to the result
result.add(triplet);
}
}
// Update the frequency map with the current arr[j]
freqMap.put(
arr[j],
freqMap.getOrDefault(arr[j], 0) + 1
);
}
}
return result;
}
public static void main(String[] args) {
int[] arr = {0, -1, 2, -3, 1};
int target = -2;
List<List<Integer>> ans = threeSum(arr, target);
for (List<Integer> triplet : ans)
System.out.println(triplet.get(0) + " " +
triplet.get(1) + " " + triplet.get(2));
}
}
def threeSum(arr, target):
result = []
n = len(arr)
# Fix the first element of the triplet using index i
for i in range(n - 2):
# Stores frequency of each number seen so far between i+1 and j-1
freq_map = {}
# j scans forward, acting as the second element of the triplet
for j in range(i + 1, n):
# The third number needed to complete the sum with arr[i] and arr[j]
number_needed = target - arr[i] - arr[j]
# Check if this needed number was already seen earlier
if number_needed in freq_map:
# It may have occurred multiple times, so count all its occurrences
freq_of_number_needed = freq_map[number_needed]
# Add one triplet for each past occurrence of the needed number
for k in range(freq_of_number_needed):
# Form the triplet from arr[i], arr[j], and the needed number
triplet = [arr[i], arr[j], number_needed]
# Sort the 3 elements so the triplet has a consistent order
triplet.sort()
# Add this triplet to the result
result.append(triplet)
# Update the frequency map with the current arr[j]
freq_map[arr[j]] = freq_map.get(arr[j], 0) + 1
return result
if __name__ == "__main__":
arr = [0, -1, 2, -3, 1]
target = -2
print(threeSum(arr, target))
function threeSum(arr, target) {
const result = [];
const n = arr.length;
// Fix the first element of the triplet using index i
for (let i = 0; i < n - 2; i++) {
// Stores frequency of each number seen so far between i+1 and j-1
const freqMap = new Map();
// j scans forward, acting as the second element of the triplet
for (let j = i + 1; j < n; j++) {
// The third number needed to complete the sum with arr[i] and arr[j]
const numberNeeded = target - arr[i] - arr[j];
// Check if this needed number was already seen earlier
if (freqMap.has(numberNeeded)) {
// It may have occurred multiple times, so count all its occurrences
const freqOfNumberNeeded = freqMap.get(numberNeeded);
// Add one triplet for each past occurrence of the needed number
for (let k = 0; k < freqOfNumberNeeded; k++) {
// Form the triplet from arr[i], arr[j], and the needed number
const triplet = [arr[i], arr[j], numberNeeded];
// Sort the 3 elements so the triplet has a consistent order
triplet.sort((a, b) => a - b);
// Add this triplet to the result
result.push(triplet);
}
}
// Update the frequency map with the current arr[j]
freqMap.set(arr[j], (freqMap.get(arr[j]) || 0) + 1);
}
}
return result;
}
// Driver Code
const arr = [0, -1, 2, -3, 1];
const target = -2;
const ans = threeSum(arr, target);
ans.forEach(triplet => {
console.log(triplet[0] + " " + triplet[1] + " " + triplet[2]);
});
Output
-3 0 1 -3 -1 2