Cover image for 面试经典150题 P373 查找和最小的K对数字

面试经典150题 P373 查找和最小的K对数字

字数 597
阅读
访客

时间轴

时间轴

2025-12-08

init


题目:

这题不能用双指针,因为不是线性的,用堆解决的核心是先把 {nums1[0],nums2[j]} 都放入堆中(0 <= j <= nums2.size()),然后从堆中去除最小和的那一对{i,j}, j 不变的情况下比它大的值中{i+1, j}最小。

那为什么可以让 j 不变呢?因为 j 的推进(即 j+1)已经在初始化阶段全部加入堆({num1[0], nums2[j]})

示例 1 的nums1 = [1, 7, 11]nums2 = [2, 4, 6]。我们把每个数对的和算出来,可以得到一个矩阵 M M ,其中 Mi,j=nums1[i]+nums2[j] M_{i,j} = nums1[i] + nums2[j]

M=[35791113131517]M = \begin{bmatrix} 3 & 5 & 7 \\ 9 & 11 & 13 \\ 13 & 15 & 17 \end{bmatrix}

由于nums2是递增的,所以矩阵每一行都是递增的。问题相当于: 合并 n n 个升序列表,找前 k k 小元素。(其中 n n nums1的长度) 根据 P23 合并 K 个升序链表 的堆的做法:

  1. 把矩阵每一行的第一个数 Mi,0 M_{i,0} 及其位置 (i,0) (i, 0) 加到最小堆中。
  2. 循环 k k 次。
  3. 每次循环,弹出堆顶,把堆顶 Mi,j M*{i,j} 的对应数对加入答案,把堆顶右边元素 Mi,j+1 M*{i,j+1} 及其位置 (i,j+1) (i, j+1) 入堆。
1234567891011121314151617181920212223242526272829303132333435363738394041424344
#include <vector>#include <queue>#include <utility>#include <array>using std::vector;using std::pair;using std::priority_queue;using std::array;class Solution {    public:        vector<vector<int> > kSmallestPairs(vector<int> &nums1,                                            vector<int> &nums2, int k)        {                vector<vector<int> > res;                if (nums1.empty() || nums2.empty() || k == 0)                        return res;                auto cmp = [&](const array<int, 2> &a, const array<int, 2> &b) {                        return nums1[a[0]] + nums2[a[1]] >                               nums1[b[0]] + nums2[b[1]];                };                priority_queue<array<int, 2>, vector<array<int, 2> >,                               decltype(cmp)>                        pq(cmp);                for (int i = 0; i < nums1.size() && i < k; i++) {                        pq.push({ i, 0 });                }                while (k-- && !pq.empty()) {                        auto [i, j] = pq.top();                        pq.pop();                        res.push_back({ nums1[i], nums2[j] });                        if (j + 1 < nums2.size()) {                                pq.push({ i, j+1 });                        }                }                return res;        }};
评论加载中…