Find K Pairs with Smallest Sums — Medium Problem & Solution

Two arrays sorted in non-decreasing order are given. A pair [u, v] takes one number from each.

  • Difficulty: Medium
  • Topics: Arrays, Heap
  • Asked at: Amazon, Google, LinkedIn
  • Time limit: 2 s
  • Memory limit: 256 MB
  • Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby

Problem statement

Two arrays sorted in non-decreasing order are given. A pair [u, v] takes one number from each.

Return the k pairs with the smallest sums, ordered by sum ascending; ties are broken by the smaller u, then the smaller v. If fewer than k pairs exist, return all of them.

Example 1

Input: nums1 = [1,7,11], nums2 = [2,4,6], k = 3
Output: [[1,2],[1,4],[1,6]]

Example 2

Input: nums1 = [1,1,2], nums2 = [1,2,3], k = 2
Output: [[1,1],[1,1]]
Explanation: Both 1s in `nums1` pair with the 1 in `nums2`.

Example 3

Input: nums1 = [1,2], nums2 = [3], k = 3
Output: [[1,3],[2,3]]
Explanation: Only two pairs exist.

Constraints

  • 1 <= nums1.length, nums2.length <= 1000
  • -10^9 <= nums1[i], nums2[i] <= 10^9
  • nums1 and nums2 are sorted in non-decreasing order.
  • 1 <= k <= 1000
  • The pairs are returned sorted by sum, then by u, then by v.

How to solve Find K Pairs with Smallest Sums

Keep a frontier of candidate pairs in a min-heap. Both arrays are sorted, so the next-smallest pair is always one step to the right of a pair already taken.

Approach

  1. Push [i, 0] for the first min(n, k) rows — no more can ever be needed.
  2. Pop the smallest, record [nums1[i], nums2[j]].
  3. Push [i, j + 1] if that column exists.
  4. Stop after k pops or when the heap empties.

Why it works

Only min(n, k) rows need seeding, because the answer can hold at most k pairs and each row contributes its smallest first. Ordering the heap on (sum, u, v) rather than the sum alone is what makes the output deterministic — without it, equal sums could come out in any order and two correct implementations would disagree.

Complexity

  • Time — O(k log k)
  • Space — O(k)

Pitfalls

  • Seeding every row is wasteful when n far exceeds k.
  • Pushing both [i+1, j] and [i, j+1] duplicates pairs unless visits are tracked.
  • Fewer than k pairs may exist; the loop must also stop on an empty heap.

Reference solution

Python

from typing import List
import heapq

def kSmallestPairs(nums1: List[int], nums2: List[int], k: int) -> List[List[int]]:
    n, m = len(nums1), len(nums2)
    heap = []
    for i in range(min(n, k)):
        heapq.heappush(heap, (nums1[i] + nums2[0], nums1[i], nums2[0], i, 0))
    out = []
    while len(out) < k and heap:
        _, u, v, i, j = heapq.heappop(heap)
        out.append([u, v])
        if j + 1 < m:
            heapq.heappush(heap, (nums1[i] + nums2[j + 1], nums1[i], nums2[j + 1], i, j + 1))
    return out

JavaScript

var kSmallestPairs = function(nums1, nums2, k) {
    var n = nums1.length, m = nums2.length;
    var heap = [];
    var less = function(a, b) {
        var sa = nums1[a[0]] + nums2[a[1]], sb = nums1[b[0]] + nums2[b[1]];
        if (sa !== sb) return sa < sb;
        if (nums1[a[0]] !== nums1[b[0]]) return nums1[a[0]] < nums1[b[0]];
        return nums2[a[1]] < nums2[b[1]];
    };
    var push = function(v) {
        heap.push(v);
        var i = heap.length - 1;
        while (i > 0) {
            var p = (i - 1) >> 1;
            if (!less(heap[i], heap[p])) break;
            var t = heap[p]; heap[p] = heap[i]; heap[i] = t;
            i = p;
        }
    };
    var pop = function() {
        var top = heap[0];
        var last = heap.pop();
        if (heap.length > 0) {
            heap[0] = last;
            var i = 0;
            for (;;) {
                var l = 2 * i + 1, r = l + 1, s = i;
                if (l < heap.length && less(heap[l], heap[s])) s = l;
                if (r < heap.length && less(heap[r], heap[s])) s = r;
                if (s === i) break;
                var t = heap[s]; heap[s] = heap[i]; heap[i] = t;
                i = s;
            }
        }
        return top;
    };
    var limit = Math.min(n, k);
    for (var i2 = 0; i2 < limit; i2++) push([i2, 0]);
    var out = [];
    while (out.length < k && heap.length > 0) {
        var cur = pop();
        out.push([nums1[cur[0]], nums2[cur[1]]]);
        if (cur[1] + 1 < m) push([cur[0], cur[1] + 1]);
    }
    return out;
};

Also on the editorial tab: C, C#, C++, Go, Java, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.

All 667 arrays problems · the whole catalogue