Open In App

3 Sum - Find all Triplets with Given Sum

Last Updated : 20 Oct, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

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.

[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++
// 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
// 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
// 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
# 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#
// 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
// 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++
// 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
// 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
# 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#
// 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
// 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



Next Article
Article Tags :
Practice Tags :

Similar Reads