Given an array arr[] and an integer target, find all distinct pairs of elements whose sum is equal to target. Return the list of pairs sorted lexicographically by the first element, and then by the second element if necessary.
Note: A pair (a, b) is considered the same as (b, a), and duplicate values at different indices are also considered the same pair.
Examples:
Input: arr[] = [1, 5, 7, -1, 5], target = 6
Output: [[1, 5], [-1, 7]]
Explanation: Pairs with sum 6 are (1, 5) and (-1, 7).Input: arr[] = [1, 1, 1, 1], target = 2
Output: [[1, 1]]
Explanation: Pairs with sum 2 are (1, 1).Input: arr[] = [10, 12, 10, 15, -1], target = 125
Output: []
Explanation: No pairs with sum 125.
Table of Content
[Naive Approach] Check All Pairs and Avoid Duplicates - O(n^2) Time and O(1) Space
The idea is to consider every possible pair of elements and check whether their sum is equal to target. Since duplicate values at different indices are considered the same pair, we use a third loop to check whether the pair has already been added to the result.
Working of the Approach:
- Use two loops to consider every possible pair (arr[i], arr[j]).
- If arr[i] + arr[j] equals target, consider the pair as a candidate.
- Use a third loop to check whether the same pair has already been added to the result.
- After checking all pairs, sort the result lexicographically.
#include <bits/stdc++.h>
using namespace std;
vector<vector<int>> distinctPairs(vector<int>& arr, int target) {
vector<vector<int>> ans;
for (int i = 0; i < arr.size(); i++) {
for (int j = i + 1; j < arr.size(); j++) {
if (arr[i] + arr[j] != target)
continue;
vector<int> pair = {min(arr[i], arr[j]), max(arr[i], arr[j])};
bool found = false;
// Check whether the pair is already present.
for (auto &p : ans) {
if (p == pair) {
found = true;
break;
}
}
if (!found)
ans.push_back(pair);
}
}
// Sort pairs lexicographically.
sort(ans.begin(), ans.end());
return ans;
}
int main() {
vector<int> arr = {1, 5, 7, -1, 5};
int target = 6;
vector<vector<int>> ans = distinctPairs(arr, target);
for (auto &p : ans)
cout << "[" << p[0] << ", " << p[1] << "] ";
return 0;
}
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
class GFG {
static List<List<Integer>> distinctPairs(int[] arr, int target) {
List<List<Integer>> ans = new ArrayList<>();
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] + arr[j] != target)
continue;
List<Integer> pair = Arrays.asList(
Math.min(arr[i], arr[j]),
Math.max(arr[i], arr[j])
);
boolean found = false;
// Check whether the pair is already present.
for (List<Integer> p : ans) {
if (p.equals(pair)) {
found = true;
break;
}
}
if (!found)
ans.add(pair);
}
}
// Sort pairs lexicographically.
Collections.sort(ans, (a, b) -> {
if (!a.get(0).equals(b.get(0)))
return Integer.compare(a.get(0), b.get(0));
return Integer.compare(a.get(1), b.get(1));
});
return ans;
}
public static void main(String[] args) {
int[] arr = {1, 5, 7, -1, 5};
int target = 6;
System.out.println(distinctPairs(arr, target));
}
}
def distinctPairs(arr, target):
ans = []
for i in range(len(arr)):
for j in range(i + 1, len(arr)):
if arr[i] + arr[j] != target:
continue
pair = [min(arr[i], arr[j]), max(arr[i], arr[j])]
# Check whether the pair is already present.
if pair not in ans:
ans.append(pair)
# Sort pairs lexicographically.
ans.sort()
return ans
if __name__ == "__main__":
arr = [1, 5, 7, -1, 5]
target = 6
print(distinctPairs(arr, target))
using System;
using System.Collections.Generic;
class GFG {
static List<List<int>> distinctPairs(int[] arr, int target) {
List<List<int>> ans = new List<List<int>>();
for (int i = 0; i < arr.Length; i++) {
for (int j = i + 1; j < arr.Length; j++) {
if (arr[i] + arr[j] != target)
continue;
List<int> pair = new List<int> {
Math.Min(arr[i], arr[j]),
Math.Max(arr[i], arr[j])
};
bool found = false;
// Check whether the pair is already present.
foreach (List<int> p in ans) {
if (p[0] == pair[0] && p[1] == pair[1]) {
found = true;
break;
}
}
if (!found)
ans.Add(pair);
}
}
// Sort pairs lexicographically.
ans.Sort((a, b) => {
int first = a[0].CompareTo(b[0]);
return first != 0 ? first : a[1].CompareTo(b[1]);
});
return ans;
}
static void Main() {
int[] arr = {1, 5, 7, -1, 5};
int target = 6;
List<List<int>> ans = distinctPairs(arr, target);
foreach (List<int> p in ans)
Console.Write("[" + p[0] + ", " + p[1] + "] ");
}
}
function distinctPairs(arr, target) {
let ans = [];
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arr[i] + arr[j] !== target)
continue;
let pair = [
Math.min(arr[i], arr[j]),
Math.max(arr[i], arr[j])
];
// Check whether the pair is already present.
let found = ans.some(
p => p[0] === pair[0] && p[1] === pair[1]
);
if (!found)
ans.push(pair);
}
}
// Sort pairs lexicographically.
ans.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
return ans;
}
// Driver Code
let arr = [1, 5, 7, -1, 5];
let target = 6;
console.log(distinctPairs(arr, target));
Output
[-1, 7] [1, 5]
[Better Approach] Use Two Pointers - O(n log n) Time and O(1) Space
The idea is to first sort the array and then use two pointers to find pairs whose sum is equal to target.
One pointer starts from the beginning and the other from the end.
- If the current sum is smaller than target, move the left pointer forward.
- If it is greater, move the right pointer backward.
- When the sum equals target, add the pair and skip duplicate values.
#include <bits/stdc++.h>
using namespace std;
vector<vector<int>> distinctPairs(vector<int>& arr, int target) {
vector<vector<int>> ans;
sort(arr.begin(), arr.end());
int left = 0, right = arr.size() - 1;
while (left < right) {
int sum = arr[left] + arr[right];
if (sum == target) {
ans.push_back({arr[left], arr[right]});
// Skip duplicate values.
int leftVal = arr[left];
int rightVal = arr[right];
while (left < right && arr[left] == leftVal)
left++;
while (left < right && arr[right] == rightVal)
right--;
}
else if (sum < target) {
left++;
}
else {
right--;
}
}
return ans;
}
int main() {
vector<int> arr = {1, 5, 7, -1, 5};
int target = 6;
vector<vector<int>> ans = distinctPairs(arr, target);
for (auto &p : ans)
cout << "[" << p[0] << ", " << p[1] << "] ";
return 0;
}
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
class GFG {
static List<List<Integer>> distinctPairs(int[] arr, int target) {
List<List<Integer>> ans = new ArrayList<>();
Arrays.sort(arr);
int left = 0, right = arr.length - 1;
while (left < right) {
int sum = arr[left] + arr[right];
if (sum == target) {
ans.add(Arrays.asList(arr[left], arr[right]));
// Skip duplicate values.
int leftVal = arr[left];
int rightVal = arr[right];
while (left < right && arr[left] == leftVal)
left++;
while (left < right && arr[right] == rightVal)
right--;
}
else if (sum < target) {
left++;
}
else {
right--;
}
}
return ans;
}
public static void main(String[] args) {
int[] arr = {1, 5, 7, -1, 5};
int target = 6;
System.out.println(distinctPairs(arr, target));
}
}
def distinctPairs(arr, target):
ans = []
arr.sort()
left, right = 0, len(arr) - 1
while left < right:
total = arr[left] + arr[right]
if total == target:
ans.append([arr[left], arr[right]])
# Skip duplicate values.
left_val = arr[left]
right_val = arr[right]
while left < right and arr[left] == left_val:
left += 1
while left < right and arr[right] == right_val:
right -= 1
elif total < target:
left += 1
else:
right -= 1
return ans
if __name__ == "__main__":
arr = [1, 5, 7, -1, 5]
target = 6
print(distinctPairs(arr, target))
using System;
using System.Collections.Generic;
class GFG {
static List<List<int>> distinctPairs(int[] arr, int target) {
List<List<int>> ans = new List<List<int>>();
Array.Sort(arr);
int left = 0, right = arr.Length - 1;
while (left < right) {
int sum = arr[left] + arr[right];
if (sum == target) {
ans.Add(new List<int> { arr[left], arr[right] });
// Skip duplicate values.
int leftVal = arr[left];
int rightVal = arr[right];
while (left < right && arr[left] == leftVal)
left++;
while (left < right && arr[right] == rightVal)
right--;
}
else if (sum < target) {
left++;
}
else {
right--;
}
}
return ans;
}
static void Main() {
int[] arr = {1, 5, 7, -1, 5};
int target = 6;
List<List<int>> ans = distinctPairs(arr, target);
foreach (List<int> p in ans)
Console.Write("[" + p[0] + ", " + p[1] + "] ");
}
}
function distinctPairs(arr, target) {
let ans = [];
arr.sort((a, b) => a - b);
let left = 0, right = arr.length - 1;
while (left < right) {
let sum = arr[left] + arr[right];
if (sum === target) {
ans.push([arr[left], arr[right]]);
// Skip duplicate values.
let leftVal = arr[left];
let rightVal = arr[right];
while (left < right && arr[left] === leftVal)
left++;
while (left < right && arr[right] === rightVal)
right--;
}
else if (sum < target) {
left++;
}
else {
right--;
}
}
return ans;
}
// Driver Code
let arr = [1, 5, 7, -1, 5];
let target = 6;
console.log(distinctPairs(arr, target));
Output
[-1, 7] [1, 5]
[Expected Approach] Use Hash Map - O(n) Time and O(n) Space
The idea is to use a hash map to store the frequency of each element in the array.
For every element x, we check whether its complement (target - x) exists in the hash map. If the complement exists, (x, target - x) forms a valid pair. We add each distinct pair only once by processing the smaller value first.
Working of the Approach:
- Create a hash map to store the frequency of each element.
- Traverse the array and store the frequency of every element in the hash map.
- Traverse the array again and consider each element x.
- Calculate its complement as target - x.
- If the complement exists and x <= complement, add the pair (x, complement) to the result.
- Remove or mark the processed values to ensure the same pair is not added again.
#include <bits/stdc++.h>
using namespace std;
vector<vector<int>> distinctPairs(vector<int>& arr, int target) {
vector<vector<int>> ans;
unordered_map<int, int> freq;
for (int x : arr)
freq[x]++;
for (auto &[x, count] : freq) {
int y = target - x;
if (freq.find(y) == freq.end())
continue;
if (x > y)
continue;
if (x == y && count < 2)
continue;
ans.push_back({x, y});
}
// Sort pairs lexicographically.
sort(ans.begin(), ans.end());
return ans;
}
int main() {
vector<int> arr = {1, 5, 7, -1, 5};
int target = 6;
vector<vector<int>> ans = distinctPairs(arr, target);
for (auto &p : ans)
cout << "[" << p[0] << ", " << p[1] << "] ";
return 0;
}
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Arrays;
class GFG {
static List<List<Integer>> distinctPairs(int[] arr, int target) {
List<List<Integer>> ans = new ArrayList<>();
HashMap<Integer, Integer> freq = new HashMap<>();
for (int x : arr)
freq.put(x, freq.getOrDefault(x, 0) + 1);
for (Map.Entry<Integer, Integer> entry : freq.entrySet()) {
int x = entry.getKey();
int y = target - x;
if (!freq.containsKey(y))
continue;
if (x > y)
continue;
if (x == y && entry.getValue() < 2)
continue;
ans.add(Arrays.asList(x, y));
}
// Sort pairs lexicographically.
ans.sort((a, b) -> {
if (!a.get(0).equals(b.get(0)))
return Integer.compare(a.get(0), b.get(0));
return Integer.compare(a.get(1), b.get(1));
});
return ans;
}
public static void main(String[] args) {
int[] arr = {1, 5, 7, -1, 5};
int target = 6;
System.out.println(distinctPairs(arr, target));
}
}
def distinctPairs(arr, target):
ans = {}
freq = {}
for x in arr:
freq[x] = freq.get(x, 0) + 1
for x, count in freq.items():
y = target - x
if y not in freq:
continue
if x > y:
continue
if x == y and count < 2:
continue
ans[(x, y)] = True
# Sort pairs lexicographically.
return [list(pair) for pair in sorted(ans)]
if __name__ == "__main__":
arr = [1, 5, 7, -1, 5]
target = 6
print(distinctPairs(arr, target))
using System;
using System.Collections.Generic;
class GFG {
static List<List<int>> distinctPairs(int[] arr, int target) {
List<List<int>> ans = new List<List<int>>();
Dictionary<int, int> freq = new Dictionary<int, int>();
foreach (int x in arr) {
if (!freq.ContainsKey(x))
freq[x] = 0;
freq[x]++;
}
foreach (var entry in freq) {
int x = entry.Key;
int y = target - x;
if (!freq.ContainsKey(y))
continue;
if (x > y)
continue;
if (x == y && entry.Value < 2)
continue;
ans.Add(new List<int> { x, y });
}
// Sort pairs lexicographically.
ans.Sort((a, b) => {
int first = a[0].CompareTo(b[0]);
return first != 0 ? first : a[1].CompareTo(b[1]);
});
return ans;
}
static void Main() {
int[] arr = {1, 5, 7, -1, 5};
int target = 6;
List<List<int>> ans = distinctPairs(arr, target);
foreach (List<int> p in ans)
Console.Write("[" + p[0] + ", " + p[1] + "] ");
}
}
function distinctPairs(arr, target) {
let ans = [];
let freq = new Map();
for (let x of arr)
freq.set(x, (freq.get(x) || 0) + 1);
for (let [x, count] of freq) {
let y = target - x;
if (!freq.has(y))
continue;
if (x > y)
continue;
if (x === y && count < 2)
continue;
ans.push([x, y]);
}
// Sort pairs lexicographically.
ans.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
return ans;
}
// Driver Code
let arr = [1, 5, 7, -1, 5];
let target = 6;
console.log(distinctPairs(arr, target));
Output
[-1, 7] [1, 5]