Algorithms first

查找和最小的 K 对数字 · 交互式算法学习

返回和最小的 k 对数字。

#373 ·

查找和最小的 K 对数字

Find K Pairs with Smallest Sums

测试用例nums1 = [1,7,11], nums2 = [2,4,6], k = 3
栈 / 队列 / 堆3 个关键状态
步骤 1每一行首对入堆:1+2、7+2、11+2。heap
队首
1+2
1+4
1+6
7+2
11+2
队尾
推荐

每行首对入最小堆

时间 O(k log min(k,m))空间 O(min(k,m))

每个 nums1[i] 对应一行递增和;堆中维护各行当前最小对。

1function kSmallestPairs(a, b, k) {2  if (!a.length || !b.length || !k) return [];3  const heap = [];4  const push = x => {5    heap.push(x);6    let i = heap.length - 1;7    while (i) {8      const p = (i - 1) >> 1;9      if (heap[p][0] <= heap[i][0]) break;10      [heap[p], heap[i]] = [heap[i], heap[p]];11      i = p12    }13  };14  const pop = () => {15    const top = heap[0],16      last = heap.pop();17    if (heap.length) {18      heap[0] = last;19      for (let i = 0;;) {20        let best = i,21          l = i * 2 + 1,22          r = l + 1;23        if (l < heap.length && heap[l][0] < heap[best][0]) best = l;24        if (r < heap.length && heap[r][0] < heap[best][0]) best = r;25        if (best === i) break;26        [heap[i], heap[best]] = [heap[best], heap[i]];27        i = best28      }29    }30    return top31  };32  for (let i = 0; i < Math.min(k, a.length); i++) push([a[i] + b[0], i, 0]);33  const out = [];34  while (k-- && heap.length) {35    const [, i, j] = pop();36    out.push([a[i], b[j]]);37    if (j + 1 < b.length) push([a[i] + b[j + 1], i, j + 1])38  }39  return out;40}
多语言参考

Java · C++ · Go

来源 · CC BY-SA 4.0 ↗

这是一组同题正确实现,独立于上方当前动画方法;不同语言可能采用另一种正确策略。

1class Solution {2    public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {3        PriorityQueue<int[]> q = new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));4        for (int i = 0; i < Math.min(nums1.length, k); ++i) {5            q.offer(new int[] {nums1[i] + nums2[0], i, 0});6        }7        List<List<Integer>> ans = new ArrayList<>();8        while (!q.isEmpty() && k > 0) {9            int[] e = q.poll();10            ans.add(Arrays.asList(nums1[e[1]], nums2[e[2]]));11            --k;12            if (e[2] + 1 < nums2.length) {13                q.offer(new int[] {nums1[e[1]] + nums2[e[2] + 1], e[1], e[2] + 1});14            }15        }16        return ans;17    }18}
交互式算法学习

从执行步骤真正理解 LeetCode 经典 150

本站整理 150 道高频算法面试题和 302 种解法。动画方法同步展示 JavaScript 与 Python;每题另提供 Java、C++ 与 Go 同题参考实现。

多形态可视化数组、矩阵、DP 表、递归树、树图、链表、栈队列堆、区间和状态机按解法选择。
动画与代码同步当前状态、步骤说明、变量和代码高亮保持一一对应,可逐步播放和回退。
适合面试复习每种方案都给出思路、时间复杂度、空间复杂度、测试用例和 LeetCode 中文原题入口。
AlgoViz Lab

查找和最小的 K 对数字 · 解法对比

返回和最小的 k 对数字。

测试用例
nums1 = [1,7,11], nums2 = [2,4,6], k = 3
题目分类
解法对比
2
方案 1

枚举全部数对排序

生成笛卡尔积,按和排序取前 k。

时间
O(mn log mn)
空间
O(mn)
方案 2

每行首对入最小堆

每个 nums1[i] 对应一行递增和;堆中维护各行当前最小对。

时间
O(k log min(k,m))
空间
O(min(k,m))