Given two integer arrays a[] and b[] of the same length, and an positive integer k, the goal is to find the top k maximum sum combinations, where each combination is formed by adding one element from a and one from b.
Each index from both arrays can be used at most once in a pair. Return the k largest sums in descending order.
Examples:
Input: a[] = [3, 2], b[] = [1, 4], k = 2
Output: [7, 6]
Explanation: Possible sums: 3 + 1 = 4, 3 + 4 = 7, 2 + 1 = 3, 2 + 4 = 6, Top 2 sums are 7 and 6.Input: a[] = [1, 4, 2, 3], b[] = [2, 5, 1, 6], k = 3
Output: [10, 9, 9]
Explanation: The top 3 maximum possible sums are : 4 + 6 = 10, 3 + 6 = 9, and 4 + 5 = 9.
Table of Content
[Naive Approach] Generate All Combinations - O(n^2 × log (n^ 2)) Time and O(n^2) Space
The idea is to compute all possible sum combinations by pairing each element from array
a[]with every element from arrayb[].
- Since each element in
acan form a pair with every element inb, we use a nested loop to generate all such sums.- After generating pair sums, we sort them in descending order and collect the top
kvalues as the final result.
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
vector<int> topKSumPairs(vector<int>& a, vector<int>& b, int k) {
int n = a.size();
// store all possible pair sums
vector<int> allpossible;
// generate all possible sums by pairing every
// element of 'a' with every element of 'b'
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
int currSum = a[i] + b[j];
allpossible.push_back(currSum);
}
}
// sort the sums in descending order to
// get the largest ones first
sort(allpossible.begin(), allpossible.end(), greater<int>());
// extract the top 'k' largest sums
vector<int> res;
for (int i = 0; i < k; i++) {
res.push_back(allpossible[i]);
}
return res;
}
int main() {
vector<int> a = {1, 4, 2, 3};
vector<int> b = {2, 5, 1, 6};
int k = 3;
vector<int> res = topKSumPairs(a, b, k);
for (int sum : res) {
cout << sum << " ";
}
return 0;
}
import java.util.ArrayList;
import java.util.Collections;
class GfG {
public static ArrayList<Integer> topKSumPairs(int[] a, int[] b, int k) {
int n = a.length;
// store all possible pair sums
ArrayList<Integer> allpossible = new ArrayList<>();
// generate all possible sums by pairing every
// element of 'a' with every element of 'b'
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
int currSum = a[i] + b[j];
allpossible.add(currSum);
}
}
// sort the sums in descending order to
// get the largest ones first
Collections.sort(allpossible, Collections.reverseOrder());
// extract the top 'k' largest sums
ArrayList<Integer> res = new ArrayList<>();
for (int i = 0; i < k; i++) {
res.add(allpossible.get(i));
}
return res;
}
public static void main(String[] args) {
int[] a = {1, 4, 2, 3};
int[] b = {2, 5, 1, 6};
int k = 3;
ArrayList<Integer> res = topKSumPairs(a, b, k);
for (int sum : res) {
System.out.print(sum + " ");
}
}
}
def topKSumPairs(a, b, k):
n = len(a)
# store all possible pair sums
allpossible = []
# generate all possible sums by pairing every
# element of 'a' with every element of 'b'
for i in range(n):
for j in range(n):
currSum = a[i] + b[j]
allpossible.append(currSum)
# sort the sums in descending order to
# get the largest ones first
allpossible.sort(reverse=True)
# extract the top 'k' largest sums
res = []
for i in range(k):
res.append(allpossible[i])
return res
if __name__ == "__main__":
a = [1, 4, 2, 3]
b = [2, 5, 1, 6]
k = 3
res = topKSumPairs(a, b, k)
for sum in res:
print(sum, end=" ")
using System;
using System.Collections.Generic;
class GfG
{
public static List<int> topKSumPairs(int[] a, int[] b, int k)
{
int n = a.Length;
// Store all possible pair sums
List<int> allpossible = new List<int>();
// Generate all possible sums
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
int currSum = a[i] + b[j];
allpossible.Add(currSum);
}
}
// Sort in descending order
allpossible.Sort((x, y) => y.CompareTo(x));
// Extract top k sums
List<int> res = new List<int>();
for (int i = 0; i < k; i++)
{
res.Add(allpossible[i]);
}
return res;
}
public static void Main()
{
int[] a = { 1, 4, 2, 3 };
int[] b = { 2, 5, 1, 6 };
int k = 3;
List<int> res = topKSumPairs(a, b, k);
foreach (int sum in res)
{
Console.Write(sum + " ");
}
}
}
function topKSumPairs(a, b, k) {
const n = a.length;
// store all possible pair sums
let allpossible = [];
// generate all possible sums by pairing every
// element of 'a' with every element of 'b'
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
let currSum = a[i] + b[j];
allpossible.push(currSum);
}
}
// sort the sums in descending order to
// get the largest ones first
allpossible.sort((x, y) => y - x);
// extract the top 'k' largest sums
let res = [];
for (let i = 0; i < k; i++) {
res.push(allpossible[i]);
}
return res;
}
// Driver Code
let a = [ 1, 4, 2, 3 ];
let b = [ 2, 5, 1, 6 ];
let k = 3;
let res = topKSumPairs(a, b, k);
console.log(res.join(" "));
Output
10 9 9
[Better Approach] Heap-Based Top-K Pair Sum Approach - O(n^2 × log k) Time and O(k) Space
- Generate all possible pair sums by adding each element from array
a[]to each element from arrayb[].- A min-heap of size
kis used to maintain the topkmaximum sums. For every new pair sum, we insert it into the heap if it’s among the largestkseen so far.- We extract and reverse the heap to return the top
ksums in descending order.
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
vector<int> topKSumPairs(vector<int>& a, vector<int>& b, int k) {
int n = a.size();
// min-heap to keep track of the top k maximum pair sums
priority_queue<int, vector<int>, greater<int>> minHeap;
// generate all possible pair sums from a[i] + b[j]
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
int currSum = a[i] + b[j];
// the heap has less than k elements, add the current sum
if ((int)minHeap.size() < k) {
minHeap.push(currSum);
}
// current sum is greater than the smallest in heap, replace it
else if (currSum > minHeap.top()) {
minHeap.pop();
minHeap.push(currSum);
}
}
}
// extract elements from the heap and store in result
vector<int> res;
while (!minHeap.empty()) {
res.push_back(minHeap.top());
minHeap.pop();
}
// convert to descending order as required
reverse(res.begin(), res.end());
return res;
}
int main() {
vector<int> a = {1, 4, 2, 3};
vector<int> b = {2, 5, 1, 6};
int k = 3;
vector<int> res = topKSumPairs(a, b, k);
for (int sum : res) {
cout << sum << " ";
}
return 0;
}
import java.util.PriorityQueue;
import java.util.Collections;
import java.util.ArrayList;
class GfG {
public static ArrayList<Integer> topKSumPairs(int[] a, int[] b, int k) {
int n = a.length;
// min-heap to keep track of the top k maximum pair sums
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
// generate all possible pair sums from a[i] + b[j]
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
int currSum = a[i] + b[j];
// the heap has less than k elements, add the current sum
if (minHeap.size() < k) {
minHeap.offer(currSum);
}
// current sum is greater than the smallest in heap, replace it
else if (currSum > minHeap.peek()) {
minHeap.poll();
minHeap.offer(currSum);
}
}
}
// Extract elements from the heap and store in result
ArrayList<Integer> res = new ArrayList<>();
while (!minHeap.isEmpty()) {
res.add(minHeap.poll());
}
// Convert to descending order as required
Collections.reverse(res);
return res;
}
public static void main(String[] args) {
int[] a = {1, 4, 2, 3};
int[] b = {2, 5, 1, 6};
int k = 3;
ArrayList<Integer> res = topKSumPairs(a, b, k);
for (int sum : res) {
System.out.print(sum + " ");
}
}
}
import heapq
def topKSumPairs(a, b, k):
n = len(a)
# min-heap to keep track of the top k maximum pair sums
minHeap = []
# generate all possible pair sums from a[i] + b[j]
for i in range(n):
for j in range(n):
currSum = a[i] + b[j]
# the heap has less than k elements, add the current sum
if len(minHeap) < k:
heapq.heappush(minHeap, currSum)
# current sum is greater than the smallest pair
# sum in the heap then replace it
elif currSum > minHeap[0]:
heapq.heappop(minHeap)
heapq.heappush(minHeap, currSum)
# extract elements from heap and store in result
res = []
while minHeap:
res.append(heapq.heappop(minHeap))
# convert to descending order as required
res.reverse()
return res
if __name__ == "__main__":
a = [1, 4, 2, 3]
b = [2, 5, 1, 6]
k = 3
res = topKSumPairs(a, b, k)
print(" ".join(map(str, res)))
using System;
using System.Collections.Generic;
class GfG {
public static List<int> topKSumPairs(int[] a, int[] b, int k) {
int n = a.Length;
// Min-heap to keep track of top k largest pair sums
SortedSet<(int sum, int index)> minHeap = new SortedSet<(int, int)>();
int idx = 0;
// Generate all possible pair sums
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
int currSum = a[i] + b[j];
if (minHeap.Count < k) {
minHeap.Add((currSum, idx++));
}
else {
// If current sum is greater than the smallest in heap
if (currSum > minHeap.Min.sum) {
minHeap.Remove(minHeap.Min);
minHeap.Add((currSum, idx++));
}
}
}
}
// Extract results and sort in descending order
List<int> res = new List<int>();
foreach (var pair in minHeap) {
res.Add(pair.sum);
}
// Descending order
res.Sort((x, y) => y.CompareTo(x));
return res;
}
public static void Main() {
int[] a = {1, 4, 2, 3};
int[] b = {2, 5, 1, 6};
int k = 3;
List<int> res = topKSumPairs(a, b, k);
foreach (int sum in res) {
Console.Write(sum + " ");
}
}
}
function topKSumPairs(a, b, k) {
let n = a.length;
// min-heap to keep track of the top k maximum pair sums
let minHeap = [];
// generate all possible pair sums from a[i] + b[j]
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
let currSum = a[i] + b[j];
// the heap has less than k elements, add the current sum
if (minHeap.length < k) {
minHeap.push(currSum);
minHeap.sort((x, y) => x - y);
}
// current sum is greater than the smallest pair
// sum in the heap then replace it
else if (currSum > minHeap[0]) {
minHeap.shift(); // remove smallest
minHeap.push(currSum);
minHeap.sort((x, y) => x - y);
}
}
}
// convert to descending order as required
return minHeap.sort((a, b) => b - a);
}
// Driver Code
const a = [1, 4, 2, 3];
const b = [2, 5, 1, 6];
const k = 3;
const res = topKSumPairs(a, b, k);
console.log(res.join(" "));
Output
10 9 9
[Expected Approach] Max Heap with Index Tracking - O(n × log n) Time and O(k) Space
The idea is to combine the largest elements from both arrays to form the highest possible sums.
- Sort the arrays in descending order to ensure that the sum at indices (0, 0) is the maximum.
- From this point, the next potential largest sums lie at positions (i+1, j) and (i, j+1) because of the sorted order. By exploring these candidates using a max heap and tracking visited index pairs, we efficiently gather the top k.
Steps by step approach:
- Sort both arrays
a[]andb[]in descending order to ensure the largest sums are considered first. - Initialize a max heap and insert the sum of the first elements
(a[0] + b[0])along with their indices(0, 0). - Use a set to track visited index pairs to prevent reprocessing the same combinations.
- Repeat for k iterations by popping the largest sum from the heap and adding it to the result. Then, insert the next possible combinations (i+1, j) and (i, j+1) into the heap if they are within bounds and have not been visited.
//Driver Code Starts
#include <iostream>
#include <vector>
#include <queue>
#include <set>
#include <algorithm>
using namespace std;
//Driver Code Ends
vector<int> topKSumPairs(vector<int> &a, vector<int> &b, int k) {
int n = a.size();
// sort both arrays in descending order
sort(a.rbegin(), a.rend());
sort(b.rbegin(), b.rend());
// max-heap to store {sum, {i, j}}
priority_queue<pair<int, pair<int, int>>> pq;
set<pair<int, int>> vis;
// start from the largest possible pair (0,0)
pq.push({a[0] + b[0], {0, 0}});
vis.insert({0, 0});
vector<int> res;
while (res.size() < k) {
auto top = pq.top();
pq.pop();
int sum = top.first;
int i = top.second.first;
int j = top.second.second;
res.push_back(sum);
// add next element in a if not visited
if (i + 1 < n && vis.find({i + 1, j}) == vis.end()) {
pq.push({a[i + 1] + b[j], {i + 1, j}});
vis.insert({i + 1, j});
}
// add next element in b if not visited
if (j + 1 < n && vis.find({i, j + 1}) == vis.end()) {
pq.push({a[i] + b[j + 1], {i, j + 1}});
vis.insert({i, j + 1});
}
}
//Driver Code Starts
return res;
}
int main() {
vector<int> a = {1, 4, 2, 3};
vector<int> b = {2, 5, 1, 6};
int k = 3;
vector<int> result = topKSumPairs(a, b, k);
for (int sum : result) {
cout << sum << " ";
}
return 0;
}
//Driver Code Ends
//Driver Code Starts
import java.util.ArrayList;
import java.util.Arrays;
import java.util.PriorityQueue;
//Driver Code Ends
import java.util.HashSet;
class GfG {
public static ArrayList<Integer> topKSumPairs(int[] a, int[] b, int k) {
int n = a.length;
// Sort both arrays in descending order
Arrays.sort(a);
Arrays.sort(b);
reverse(a);
reverse(b);
// Max-heap to store {sum, i, j}
PriorityQueue<int[]> pq = new PriorityQueue<>((x, y) -> y[0] - x[0]);
HashSet<String> vis = new HashSet<>();
// Start from the largest possible pair (0, 0)
pq.offer(new int[]{a[0] + b[0], 0, 0});
vis.add("0#0");
ArrayList<Integer> res = new ArrayList<>();
while (res.size() < k && !pq.isEmpty()) {
int[] top = pq.poll();
int sum = top[0], i = top[1], j = top[2];
res.add(sum);
// Try the next element in array a
if (i + 1 < n && !vis.contains((i + 1) + "#" + j)) {
pq.offer(new int[]{a[i + 1] + b[j], i + 1, j});
vis.add((i + 1) + "#" + j);
}
// Try the next element in array b
if (j + 1 < n && !vis.contains(i + "#" + (j + 1))) {
pq.offer(new int[]{a[i] + b[j + 1], i, j + 1});
vis.add(i + "#" + (j + 1));
}
}
//Driver Code Starts
return res;
}
// Helper method to reverse an array in-place
private static void reverse(int[] arr) {
int l = 0, r = arr.length - 1;
while (l < r) {
int temp = arr[l];
arr[l++] = arr[r];
arr[r--] = temp;
}
}
public static void main(String[] args) {
int[] a = {1, 4, 2, 3};
int[] b = {2, 5, 1, 6};
int k = 3;
ArrayList<Integer> result = topKSumPairs(a, b, k);
for (int val : result) {
System.out.print(val + " ");
}
}
}
//Driver Code Ends
#Driver Code Starts
import heapq
#Driver Code Ends
def topKSumPairs(a, b, k):
n = len(a)
# sort both arrays in descending order
a.sort(reverse=True)
b.sort(reverse=True)
visited = set()
heap = []
# max-heap to store {sum, {i, j}}
heapq.heappush(heap, (-(a[0] + b[0]), 0, 0))
# start from the largest possible pair (0,0)
visited.add((0, 0))
res = []
while len(res) < k:
sum_neg, i, j = heapq.heappop(heap)
res.append(-sum_neg)
# add next element in a if not visited
if i + 1 < n and (i + 1, j) not in visited:
heapq.heappush(heap, (-(a[i + 1] + b[j]), i + 1, j))
visited.add((i + 1, j))
# add next element in b if not visited
if j + 1 < n and (i, j + 1) not in visited:
heapq.heappush(heap, (-(a[i] + b[j + 1]), i, j + 1))
visited.add((i, j + 1))
return res
#Driver Code Starts
if __name__ == "__main__":
a = [1, 4, 2, 3]
b = [2, 5, 1, 6]
k = 3
result = topKSumPairs(a, b, k)
print(" ".join(map(str, result)))
#Driver Code Ends
//Driver Code Starts
using System;
using System.Collections.Generic;
class GfG {
//Driver Code Ends
public static List<int> topKSumPairs(int[] a, int[] b, int k) {
int n = a.Length;
// Sort both arrays in descending order
Array.Sort(a);
Array.Sort(b);
Array.Reverse(a);
Array.Reverse(b);
// Max-heap: SortedSet stores (sum, i, j) sorted by descending sum
var maxHeap = new SortedSet<(int, int, int)>(
Comparer<(int, int, int)>.Create((x, y) =>
x.Item1 != y.Item1 ? y.Item1.CompareTo(x.Item1) :
x.Item2 != y.Item2 ? x.Item2.CompareTo(y.Item2) :
x.Item3.CompareTo(y.Item3)
)
);
var visited = new HashSet<(int, int)>();
var result = new List<int>();
// Add initial pair (0, 0)
maxHeap.Add((a[0] + b[0], 0, 0));
visited.Add((0, 0));
while (result.Count < k && maxHeap.Count > 0) {
var top = maxHeap.Min;
maxHeap.Remove(top);
int sum = top.Item1;
int i = top.Item2, j = top.Item3;
result.Add(sum);
// Move to next element in a
if (i + 1 < n && !visited.Contains((i + 1, j))) {
maxHeap.Add((a[i + 1] + b[j], i + 1, j));
visited.Add((i + 1, j));
//Driver Code Starts
}
// Move to next element in b
if (j + 1 < n && !visited.Contains((i, j + 1))) {
maxHeap.Add((a[i] + b[j + 1], i, j + 1));
visited.Add((i, j + 1));
}
}
return result;
}
public static void Main() {
int[] a = {1, 4, 2, 3};
int[] b = {2, 5, 1, 6};
int k = 3;
List<int> res = topKSumPairs(a, b, k);
foreach (int sum in res) {
Console.Write(sum + " ");
}
}
}
//Driver Code Ends
// Custom Max Heap implementation
class MaxHeap {
constructor() {
this.heap = [];
}
push(element) {
this.heap.push(element);
// Sort the heap to maintain max-heap property (descending order)
this.heap.sort((a, b) => b[0] - a[0]);
}
pop() {
return this.heap.shift();
}
size() {
return this.heap.length;
}
}
// Function to find top k maximum sum combinations
function topKSumPairs(a, b, k) {
let n = a.length;
// Sort both arrays in descending order
a.sort((x, y) => y - x);
b.sort((x, y) => y - x);
const heap = new MaxHeap();
const used = new Set();
// Start from the largest pair (0, 0)
heap.push([a[0] + b[0], 0, 0]);
used.add(`0,0`);
//Driver Code Starts
const res = [];
// Extract top k combinations
while (res.length < k) {
const [sum, i, j] = heap.pop();
res.push(sum);
// Next element from a
if (i + 1 < n && !used.has(`${i + 1},${j}`)) {
heap.push([a[i + 1] + b[j], i + 1, j]);
used.add(`${i + 1},${j}`);
}
// Next element from b
if (j + 1 < n && !used.has(`${i},${j + 1}`)) {
heap.push([a[i] + b[j + 1], i, j + 1]);
used.add(`${i},${j + 1}`);
}
}
return res;
}
// Driver Code
const k = 3;
const a = [1, 4, 2, 3];
const b = [2, 5, 1, 6];
const result = topKSumPairs(a, b, k);
console.log(result.join(" "));
//Driver Code Ends
Output
10 9 9