Given two integer arrays arr1[] and arr2[] sorted in ascending order and an integer k. Find k pairs with smallest sums such that one element of a pair belongs to arr1[] and other element belongs to arr2[].
Examples:
Input: arr1[] = [1, 7, 11], arr2[] = [2, 4, 6], k = 3
Output: [[1, 2], [1, 4], [1, 6]]
Explanation: All possible combinations of elements from the two arrays are
[1, 2], [1, 4], [1, 6], [7, 2], [7, 4], [7, 6], [11, 2], [11, 4], [11, 6]. Among these, the three pairs with the minimum sums are [1, 2], [1, 4], [1, 6].Input: arr1[] = [1, 3], arr2[] = [2, 4], k = 2
Output: [[1, 2], [3, 2]]
Explanation: All possible combinations are [1, 2], [1, 4], [3, 2], [3, 4]. Among these, the two pairs with the minimum sums are [1, 2], [3, 2].
Table of Content
[Naive Approach] By finding all combinations - O(n1 * n2 * log (n1 * n2)) Time and O(n1*n2) Space
The idea is to generate all possible pairs from the two input arrays. This is done by iterating through each element of the first array and pairing it with every element of the second array. Once all pairs are generated, we sort them based on the sum of the elements in each pair. After sorting, the first k pairs in the sorted list are the pairs with the smallest sums.
//Driver Code Starts
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
//Driver Code Ends
// Comparator function to sort based on sum
bool comparePairs(vector<int>& a, vector<int>& b) {
return a[0] + a[1] < b[0] + b[1];
}
vector<vector<int>> kSmallestPair(vector<int>& arr1, vector<int>& arr2, int k) {
vector<vector<int>> pairs;
// Generate all possible pairs and store as {arr1[i], arr2[j]}
for (int i = 0; i < arr1.size(); i++) {
for (int j = 0; j < arr2.size(); j++) {
pairs.push_back({arr1[i], arr2[j]});
}
}
// Sort pairs based on their sum using comparator function
sort(pairs.begin(), pairs.end(), comparePairs);
// Pick first k pairs
vector<vector<int>> res;
for (int i = 0; i < k && i < pairs.size(); i++) {
res.push_back({pairs[i][0], pairs[i][1]});
}
return res;
}
//Driver Code Starts
int main() {
vector<int> arr1 = {1, 7, 11};
vector<int> arr2 = {2, 4, 6};
int k = 3;
vector<vector<int>> ans = kSmallestPair(arr1, arr2, k);
for (auto &p : ans){
cout << p[0] << " " << p[1];
cout<<endl;
}
}
//Driver Code Ends
//Driver Code Starts
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
class GFG {
//Driver Code Ends
// Comparator to sort pairs based on their sum
static Comparator<int[]> comparePairs = new Comparator<int[]>() {
public int compare(int[] a, int[] b) {
return (a[0] + a[1]) - (b[0] + b[1]);
}
};
static ArrayList<ArrayList<Integer>> kSmallestPair(int[] arr1, int[] arr2, int k) {
ArrayList<int[]> pairs = new ArrayList<>();
// Generate all possible pairs and store as {arr1[i], arr2[j]}
for (int i = 0; i < arr1.length; i++) {
for (int j = 0; j < arr2.length; j++) {
pairs.add(new int[]{arr1[i], arr2[j]});
}
}
// Sort pairs based on their sum
Collections.sort(pairs, comparePairs);
// Pick first k pairs
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
for (int i = 0; i < k && i < pairs.size(); i++) {
res.add(new ArrayList<>(Arrays.asList(pairs.get(i)[0], pairs.get(i)[1])));
}
return res;
}
//Driver Code Starts
public static void main(String[] args) {
int[] arr1 = {1, 7, 11};
int[] arr2 = {2, 4, 6};
int k = 3;
ArrayList<ArrayList<Integer>> ans = kSmallestPair(arr1, arr2, k);
for (ArrayList<Integer> p : ans) {
System.out.println(p.get(0) + " " + p.get(1));
}
}
}
//Driver Code Ends
# Comparator function to sort based on sum
def comparePairs(a):
return a[0] + a[1]
def kSmallestPairs(arr1, arr2, k):
pairs = []
# Generate all possible pairs and store as {arr1[i], arr2[j]}
for i in range(len(arr1)):
for j in range(len(arr2)):
pairs.append([arr1[i], arr2[j]])
# Sort pairs based on their sum using comparator function
pairs.sort(key=comparePairs)
# Pick first k pairs
res = []
for i in range(min(k, len(pairs))):
res.append([pairs[i][0], pairs[i][1]])
return res
if __name__ == "__main__":
#Driver Code Starts
arr1 = [1, 7, 11]
arr2 = [2, 4, 6]
k = 3
ans = kSmallestPairs(arr1, arr2, k)
for p in ans:
print(f"{p[0]} {p[1]}")
#Driver Code Ends
//Driver Code Starts
using System;
using System.Collections.Generic;
class GFG {
//Driver Code Ends
// Comparator function to sort based on sum
static int comparePairs(int[] a, int[] b) {
return (a[0] + a[1]).CompareTo(b[0] + b[1]);
}
static List<List<int>> kSmallestPair(int[] arr1, int[] arr2, int k) {
List<int[]> pairs = new List<int[]>();
// Generate all possible pairs and store as {arr1[i], arr2[j]}
for (int i = 0; i < arr1.Length; i++)
{
for (int j = 0; j < arr2.Length; j++)
{
pairs.Add(new int[] { arr1[i], arr2[j] });
}
}
// Sort pairs based on their sum using comparator function
pairs.Sort(comparePairs);
// Pick first k pairs and convert to List<List<int>>
List<List<int>> res = new List<List<int>>();
for (int i = 0; i < k && i < pairs.Count; i++)
{
res.Add(new List<int> { pairs[i][0], pairs[i][1] });
}
return res;
}
//Driver Code Starts
static void Main()
{
int[] arr1 = { 1, 7, 11 };
int[] arr2 = { 2, 4, 6 };
int k = 3;
List<List<int>> ans = kSmallestPair(arr1, arr2, k);
foreach (var p in ans)
{
Console.WriteLine(p[0] + " " + p[1]);
}
}
}
//Driver Code Ends
// Comparator function to sort based on sum
function comparePairs(a, b) {
return (a[0] + a[1]) - (b[0] + b[1]);
}
function kSmallestPair(arr1, arr2, k) {
let pairs = [];
// Generate all possible pairs and store as [arr1[i], arr2[j]]
for (let i = 0; i < arr1.length; i++) {
for (let j = 0; j < arr2.length; j++) {
pairs.push([arr1[i], arr2[j]]);
}
}
// Sort pairs based on their sum
pairs.sort(comparePairs);
// Pick first k pairs
let res = [];
for (let i = 0; i < Math.min(k, pairs.length); i++) {
res.push([pairs[i][0], pairs[i][1]]);
}
return res;
}
// Driver code
//Driver Code Starts
let arr1 = [1, 7, 11];
let arr2 = [2, 4, 6];
let k = 3;
let ans = kSmallestPair(arr1, arr2, k);
ans.forEach(p => console.log(p[0] + " " + p[1]));
//Driver Code Ends
Output
1 2 1 4 1 6
[Better Approach] Using Next Element Tracking - O(n1 * k) Time and O(n1) Space
The main idea is to keep track of which element from the second array should pair next with each element from the first array. Initially, every element in the first array is paired with the first element of the second array. Then, at each step, we find the pair with the smallest sum among all current pairs, add it to the result, and move that element’s pointer in the second array to its next element. We repeat this process until we have found K pairs.
//Driver Code Starts
#include <climits>
#include <iostream>
#include <vector>
using namespace std;
//Driver Code Ends
vector<vector<int>> kSmallestPair(vector<int> &arr1, vector<int> &arr2, int k)
{
vector<vector<int>> ans;
int n1 = arr1.size();
int n2 = arr2.size();
if (n1 == 0 || n2 == 0)
return ans;
// track next element in arr2 for each arr1[i]
vector<int> index2(n1, 0);
while (k > 0)
{
int min_sum = INT_MAX;
int min_index = -1;
// Find the next pair with minimum sum
for (int i = 0; i < n1; i++)
{
if (index2[i] < n2 && arr1[i] + arr2[index2[i]] < min_sum)
{
min_sum = arr1[i] + arr2[index2[i]];
min_index = i;
}
}
// no more pairs available
if (min_index == -1)
break;
ans.push_back({arr1[min_index], arr2[index2[min_index]]});
index2[min_index]++;
k--;
}
return ans;
}
//Driver Code Starts
int main()
{
vector<int> arr1 = {1, 7, 11};
vector<int> arr2 = {2, 4, 6};
int k = 3;
vector<vector<int>> ans = kSmallestPair(arr1, arr2, k);
for (auto &p : ans)
{
cout << p[0] << " " << p[1] << endl;
}
}
//Driver Code Ends
//Driver Code Starts
import java.util.ArrayList;
import java.util.Arrays;
class GFG {
//Driver Code Ends
static ArrayList<ArrayList<Integer>> kSmallestPair(int[] arr1, int[] arr2, int k) {
ArrayList<ArrayList<Integer>> ans = new ArrayList<>();
int n1 = arr1.length;
int n2 = arr2.length;
if (n1 == 0 || n2 == 0) return ans;
// track next element in arr2 for each arr1[i]
int[] index2 = new int[n1];
while (k > 0) {
int min_sum = Integer.MAX_VALUE;
int min_index = -1;
// Find the next pair with minimum sum
for (int i = 0; i < n1; i++) {
if (index2[i] < n2 && arr1[i] + arr2[index2[i]] < min_sum) {
min_sum = arr1[i] + arr2[index2[i]];
min_index = i;
}
}
// no more pairs available
if (min_index == -1) break;
ans.add(new ArrayList<>(Arrays.asList(arr1[min_index], arr2[index2[min_index]])));
index2[min_index]++;
k--;
}
return ans;
}
//Driver Code Starts
public static void main(String[] args) {
int[] arr1 = {1, 7, 11};
int[] arr2 = {2, 4, 6};
int k = 3;
ArrayList<ArrayList<Integer>> ans = kSmallestPair(arr1, arr2, k);
for (ArrayList<Integer> p : ans) {
System.out.println(p.get(0) + " " + p.get(1));
}
}
}
//Driver Code Ends
#Driver Code Starts
import sys
#Driver Code Ends
def kSmallestPair(arr1, arr2, k):
ans = []
n1 = len(arr1)
n2 = len(arr2)
if n1 == 0 or n2 == 0:
return ans
# track next element in arr2 for each arr1[i]
index2 = [0] * n1
while k > 0:
min_sum = sys.maxsize
min_index = -1
# Find the next pair with minimum sum
for i in range(n1):
if index2[i] < n2 and arr1[i] + arr2[index2[i]] < min_sum:
min_sum = arr1[i] + arr2[index2[i]]
min_index = i
# no more pairs available
if min_index == -1:
break
ans.append([arr1[min_index], arr2[index2[min_index]]])
index2[min_index] += 1
k -= 1
return ans
#Driver Code Starts
if __name__ == "__main__":
arr1 = [1, 7, 11]
arr2 = [2, 4, 6]
k = 3
ans = kSmallestPair(arr1, arr2, k)
for p in ans:
print(f"{p[0]} {p[1]}")
#Driver Code Ends
//Driver Code Starts
using System;
using System.Collections.Generic;
class GFG {
//Driver Code Ends
static List<List<int>> kSmallestPair(int[] arr1, int[] arr2, int k) {
List<List<int>> ans = new List<List<int>>();
int n1 = arr1.Length;
int n2 = arr2.Length;
if (n1 == 0 || n2 == 0) return ans;
// track next element in arr2 for each arr1[i]
int[] index2 = new int[n1];
while (k > 0)
{
int min_sum = int.MaxValue;
int min_index = -1;
// Find the next pair with minimum sum
for (int i = 0; i < n1; i++)
{
if (index2[i] < n2 && arr1[i] + arr2[index2[i]] < min_sum)
{
min_sum = arr1[i] + arr2[index2[i]];
min_index = i;
}
}
// no more pairs available
if (min_index == -1) break;
ans.Add(new List<int> { arr1[min_index], arr2[index2[min_index]] });
index2[min_index]++;
k--;
}
return ans;
}
//Driver Code Starts
static void Main()
{
int[] arr1 = { 1, 7, 11 };
int[] arr2 = { 2, 4, 6 };
int k = 3;
List<List<int>> ans = kSmallestPair(arr1, arr2, k);
foreach (var p in ans)
{
Console.WriteLine(p[0] + " " + p[1]);
}
}
}
//Driver Code Ends
function kSmallestPair(arr1, arr2, k) {
let ans = [];
let n1 = arr1.length;
let n2 = arr2.length;
if (n1 === 0 || n2 === 0) return ans;
// track next element in arr2 for each arr1[i]
let index2 = new Array(n1).fill(0);
while (k > 0) {
let min_sum = Number.MAX_SAFE_INTEGER;
let min_index = -1;
// Find the next pair with minimum sum
for (let i = 0; i < n1; i++) {
if (index2[i] < n2 && arr1[i] + arr2[index2[i]] < min_sum) {
min_sum = arr1[i] + arr2[index2[i]];
min_index = i;
}
}
// no more pairs available
if (min_index === -1) break;
ans.push([arr1[min_index], arr2[index2[min_index]]]);
index2[min_index]++;
k--;
}
return ans;
}
// Driver code
//Driver Code Starts
let arr1 = [1, 7, 11];
let arr2 = [2, 4, 6];
let k = 3;
let ans = kSmallestPair(arr1, arr2, k);
ans.forEach(p => console.log(p[0]+" "+p[1]));
//Driver Code Ends
Output
1 2 1 4 1 6
[Optimal Approach] Using set and Priority Queue - O(k * log k) Time and O(k) Space
We want to find the k pairs with the smallest sums from two sorted arrays. To do this efficiently, we can use a min-heap (priority queue) so that we always process the smallest sum first. Since both arrays are sorted, the smallest possible pair will be formed by the first elements of both arrays. We start by pushing this pair into the min-heap. Then, we repeatedly pop the smallest pair from the heap and push the next possible pairs — one by moving ahead in the first array, and the other by moving ahead in the second array.
We continue this process until we have processed K smallest pairs. A set is also maintained to ensure that we don’t push the same index pair multiple times.
//Driver Code Starts
#include <iostream>
#include <vector>
#include <queue>
#include <set>
using namespace std;
//Driver Code Ends
vector<vector<int>> kSmallestPair(vector<int> arr1, vector<int> arr2, int k) {
vector<vector<int>> ans;
// Min-heap to keep track of current smallest sum and indices
priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>> pq;
set<vector<int>> my_set;
// Push initial pair (arr1[0] + arr2[0]) with indices (0,0)
pq.push({arr1[0] + arr2[0], 0, 0});
my_set.insert({0, 0});
int flag = 1;
for (int count = 0; count < k && flag; count++) {
vector<int> temp = pq.top();
pq.pop();
int i = temp[1];
int j = temp[2];
// Add the current smallest pair to the answer
ans.push_back({arr1[i], arr2[j]});
flag = 0;
// Push next element in arr1 (if not already used)
if (i + 1 < arr1.size()) {
vector<int> temp1 = {i + 1, j};
if (my_set.find(temp1) == my_set.end()) {
pq.push({arr1[i + 1] + arr2[j], i + 1, j});
my_set.insert(temp1);
}
flag = 1;
}
// Push next element in arr2 (if not already used)
if (j + 1 < arr2.size()) {
vector<int> temp1 = {i, j + 1};
if (my_set.find(temp1) == my_set.end()) {
pq.push({arr1[i] + arr2[j + 1], i, j + 1});
my_set.insert(temp1);
}
flag = 1;
}
}
return ans;
}
//Driver Code Starts
int main()
{
vector<int> arr1 = {1, 7, 11};
vector<int> arr2 = {2, 4, 6};
int K = 3;
vector<vector<int>> ans = kSmallestPair(arr1, arr2, K);
// Print the K smallest sum pairs
for (auto &p : ans) {
cout << p[0] << " " << p[1] << endl;
}
return 0;
}
//Driver Code Ends
//Driver Code Starts
import java.util.ArrayList;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;
class GFG {
//Driver Code Ends
static ArrayList<ArrayList<Integer>> kSmallestPair(int[] arr1, int[] arr2, int k) {
ArrayList<ArrayList<Integer>> ans = new ArrayList<>();
if (arr1.length == 0 || arr2.length == 0 || k <= 0) return ans;
// Min-heap to keep track of current smallest sum and indices
PriorityQueue<int[]> pq = new PriorityQueue<>(new Comparator<int[]>() {
public int compare(int[] a, int[] b) {
return a[0] - b[0];
}
});
Set<String> my_set = new HashSet<>();
// Push initial pair (arr1[0] + arr2[0]) with indices (0,0)
pq.offer(new int[]{arr1[0] + arr2[0], 0, 0});
my_set.add("0,0");
while (k > 0 && !pq.isEmpty()) {
int[] temp = pq.poll();
int sum = temp[0], i = temp[1], j = temp[2];
// Add the current smallest pair to the answer
ans.add(new ArrayList<>(Arrays.asList(arr1[i], arr2[j])));
k--;
// Push next element in arr1 (if not already used)
if (i + 1 < arr1.length) {
String key1 = (i + 1) + "," + j;
if (!my_set.contains(key1)) {
pq.offer(new int[]{arr1[i + 1] + arr2[j], i + 1, j});
my_set.add(key1);
}
}
// Push next element in arr2 (if not already used)
if (j + 1 < arr2.length) {
String key2 = i + "," + (j + 1);
if (!my_set.contains(key2)) {
pq.offer(new int[]{arr1[i] + arr2[j + 1], i, j + 1});
my_set.add(key2);
}
}
}
return ans;
}
//Driver Code Starts
public static void main(String[] args)
{
int[] arr1 = {1, 7, 11};
int[] arr2 = {2, 4, 6};
int K = 3;
ArrayList<ArrayList<Integer>> ans = kSmallestPair(arr1, arr2, K);
// Print the K smallest sum pairs
for (ArrayList<Integer> p : ans) {
System.out.println(p.get(0) + " " + p.get(1));
}
}
}
//Driver Code Ends
def kSmallestPair(arr1, arr2, k):
ans = []
# Min-heap to keep track of current smallest sum and indices
import heapq
pq = []
my_set = set()
# Push initial pair (arr1[0] + arr2[0]) with indices (0,0)
heapq.heappush(pq, (arr1[0] + arr2[0], 0, 0))
my_set.add((0, 0))
flag = 1
count = 0
while count < k and flag != 0:
temp = heapq.heappop(pq)
sum_val, i, j = temp
# Add the current smallest pair to the answer
ans.append([arr1[i], arr2[j]])
flag = 0
# Push next element in arr1 (if not already used)
if i + 1 < len(arr1):
temp1 = (i + 1, j)
if temp1 not in my_set:
heapq.heappush(pq, (arr1[i + 1] + arr2[j], i + 1, j))
my_set.add(temp1)
flag = 1
# Push next element in arr2 (if not already used)
if j + 1 < len(arr2):
temp1 = (i, j + 1)
if temp1 not in my_set:
heapq.heappush(pq, (arr1[i] + arr2[j + 1], i, j + 1))
my_set.add(temp1)
flag = 1
count += 1
return ans
if __name__ == '__main__':
#Driver Code Starts
arr1 = [1, 7, 11]
arr2 = [2, 4, 6]
K = 3
ans = kSmallestPair(arr1, arr2, K)
# Print the K smallest sum pairs
for p in ans:
print(f"{p[0]} {p[1]}")
#Driver Code Ends
//Driver Code Starts
using System;
using System.Collections.Generic;
class GFG {
//Driver Code Ends
static List<List<int>> kSmallestPair(int[] arr1, int[] arr2, int k) {
List<List<int>> ans = new List<List<int>>();
if (arr1.Length == 0 || arr2.Length == 0 || k <= 0)
return ans;
// Min-heap to keep track of current smallest sum and indices
var pq = new SortedSet<Tuple<int, int, int>>(Comparer<Tuple<int, int, int>>.Create(
(a, b) => a.Item1 != b.Item1 ? a.Item1 - b.Item1 :
a.Item2 != b.Item2 ? a.Item2 - b.Item2 :
a.Item3 - b.Item3
));
var my_set = new HashSet<Tuple<int, int>>();
// Push initial pair (arr1[0] + arr2[0]) with indices (0,0)
pq.Add(Tuple.Create(arr1[0] + arr2[0], 0, 0));
my_set.Add(Tuple.Create(0, 0));
int flag = 1;
for (int count = 0; count < k && flag != 0; count++)
{
var temp = pq.Min;
pq.Remove(temp);
int i = temp.Item2;
int j = temp.Item3;
// Add the current smallest pair to the answer
ans.Add(new List<int> { arr1[i], arr2[j] });
flag = 0;
// Push next element in arr1 (if not already used)
if (i + 1 < arr1.Length)
{
var temp1 = Tuple.Create(i + 1, j);
if (!my_set.Contains(temp1))
{
pq.Add(Tuple.Create(arr1[i + 1] + arr2[j], i + 1, j));
my_set.Add(temp1);
}
flag = 1;
}
// Push next element in arr2 (if not already used)
if (j + 1 < arr2.Length)
{
var temp1 = Tuple.Create(i, j + 1);
if (!my_set.Contains(temp1))
{
pq.Add(Tuple.Create(arr1[i] + arr2[j + 1], i, j + 1));
my_set.Add(temp1);
}
flag = 1;
}
}
return ans;
}
//Driver Code Starts
static void Main()
{
int[] arr1 = { 1, 7, 11 };
int[] arr2 = { 2, 4, 6 };
int K = 3;
List<List<int>> ans = kSmallestPair(arr1, arr2, K);
// Print the K smallest sum pairs
foreach (var p in ans)
{
Console.WriteLine(p[0] + " " + p[1]);
}
}
}
//Driver Code Ends
//Driver Code Starts
// Custom Min-Heap implementation
class MinHeap {
constructor() {
this.heap = [];
}
push(val) {
this.heap.push(val);
this.heap.sort((a, b) => a[0] - b[0]);
}
pop() {
return this.heap.shift();
}
top() {
return this.heap[0];
}
size() {
return this.heap.length;
}
}
//Driver Code Ends
function kSmallestPair(arr1, arr2, k) {
let ans = [];
// Min-heap to keep track of current smallest sum and indices
let pq = new MinHeap();
let my_set = new Set();
// Push initial pair (arr1[0] + arr2[0]) with indices (0,0)
pq.push([arr1[0] + arr2[0], 0, 0]);
my_set.add("0,0");
let flag = 1;
for (let count = 0; count < k && flag; count++) {
let temp = pq.pop();
let i = temp[1];
let j = temp[2];
// Add the current smallest pair to the answer
ans.push([arr1[i], arr2[j]]);
flag = 0;
// Push next element in arr1 (if not already used)
if (i + 1 < arr1.length) {
let key = (i + 1) + "," + j;
if (!my_set.has(key)) {
pq.push([arr1[i + 1] + arr2[j], i + 1, j]);
my_set.add(key);
}
flag = 1;
}
// Push next element in arr2 (if not already used)
if (j + 1 < arr2.length) {
let key = i + "," + (j + 1);
if (!my_set.has(key)) {
pq.push([arr1[i] + arr2[j + 1], i, j + 1]);
my_set.add(key);
}
flag = 1;
}
}
return ans;
}
//Driver Code Starts
// Driver code
let arr1 = [1, 7, 11];
let arr2 = [2, 4, 6];
let K = 3;
let ans = kSmallestPair(arr1, arr2, K);
// Print the K smallest sum pairs
for (let p of ans) {
console.log(p[0] + " " + p[1]);
}
//Driver Code Ends
Output
1 2 1 4 1 6