Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LeetCode] 373. Find K Pairs with Smallest Sums #373

Open
grandyang opened this issue May 30, 2019 · 0 comments
Open

[LeetCode] 373. Find K Pairs with Smallest Sums #373

grandyang opened this issue May 30, 2019 · 0 comments

Comments

@grandyang
Copy link
Owner

grandyang commented May 30, 2019

You are given two integer arrays nums1 and nums2 sorted in ascending order and an integer k.

Define a pair (u, v) which consists of one element from the first array and one element from the second array.

Return the k pairs (u1, v1), (u2, v2), ..., (uk, vk) with the smallest sums.

Example 1:

Input: nums1 = [1,7,11], nums2 = [2,4,6], k = 3
Output: [[1,2],[1,4],[1,6]]
Explanation: The first 3 pairs are returned from the sequence: [1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6]

Example 2:

Input: nums1 = [1,1,2], nums2 = [1,2,3], k = 2
Output: [[1,1],[1,1]]
Explanation: The first 2 pairs are returned from the sequence: [1,1],[1,1],[1,2],[2,1],[1,2],[2,2],[1,3],[1,3],[2,3]

Example 3:

Input: nums1 = [1,2], nums2 = [3], k = 3
Output: [[1,3],[2,3]]
Explanation: All possible pairs are returned from the sequence: [1,3],[2,3]

Constraints:

  • 1 <= nums1.length, nums2.length <= 104
  • -109 <= nums1[i], nums2[i] <= 109
  • nums1 and nums2 both are sorted in ascending order.
  • 1 <= k <= 1000

Credits:
Special thanks to @elmirap and @StefanPochmann for adding this problem and creating all test cases.

这道题给了我们两个数组,让从每个数组中任意取出一个数字来组成不同的数字对,返回前K个和最小的数字对。那么这道题有多种解法,首先来看 brute force 的解法,这种方法从0循环到数组的个数和k之间的较小值,这样做的好处是如果k远小于数组个数时,不需要计算所有的数字对,而是最多计算 k*k 个数字对,然后将其都保存在 res 里,这时候给 res 排序,用自定义的比较器,就是和的比较,然后把比k多出的数字对删掉即可,参见代码如下(现在这种解法已经没法通过 OJ 了):

解法一:

// Time Limit Exceeded
class Solution {
public:
    vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
        vector<vector<int>> res;
        for (int i = 0; i < min((int)nums1.size(), k); ++i) {
            for (int j = 0; j < min((int)nums2.size(), k); ++j) {
                res.push_back({nums1[i], nums2[j]});
            }
        }
        sort(res.begin(), res.end(), [](vector<int> &a, vector<int> &b){return a[0] + a[1] < b[0] + b[1];});
        if (res.size() > k) res.erase(res.begin() + k, res.end());
        return res;
    }
};

我们也可以使用优先队列 priority_queue 来做,里面放一个 pair 对儿,由一个整型数和一个数组组成,其中整型数就是两个数字之和,数组就包含着两个数字,这样优先队列就可以默认按照两数组之和大小来排序,大的放前面。接下来就是遍历所有两个数字的组合,计算出两数之和 sum,然后此时判断若队列中元素没有超过k个,则此时将 sum 和两个数字组成数组组成 pair 对儿加入到队列中。若元素个数不少于k个,则需要判断队首元素中的两数组之和跟当前两数之和 sum 之间的关系,若 sum 更小,则将队首元素移除,将 sum 和两个数字组成数组组成 pair 对儿加入到队列中,这样保证了队列中一定都是两数和最小的数对儿。遍历结束后,只要把优先队列中的数对儿取出,加入到结果 res 中即可,参见代码如下:

解法二:

class Solution {
public:
    vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
        vector<vector<int>> res;
        priority_queue<pair<int, vector<int>>> pq;
        for (int num1 : nums1) {
            for (int num2 : nums2) {
                int sum = num1 + num2;
                if (pq.size() < k) {
                    pq.push({sum, {num1, num2}});
                } else if (sum < pq.top().first) {
                    pq.pop();
                    pq.push({sum, {num1, num2}});
                } else {
                    break;
                }
            }
        }
        while (!pq.empty()) {
            res.push_back(pq.top().second);
            pq.pop();
        }
        return res;
    }
};

Github 同步地址:

#373

参考资料:

https://leetcode.com/problems/find-k-pairs-with-smallest-sums/

https://leetcode.com/problems/find-k-pairs-with-smallest-sums/solutions/4058698/c-priority-queue-k-max-heap-method-most-efficient/

LeetCode All in One 题目讲解汇总(持续更新中...)

(欢迎加入博主的知识星球,博主将及时答疑解惑,并分享刷题经验与总结,快快加入吧~)

知识星球 喜欢请点赞,疼爱请打赏❤️~.~

微信打赏

|

Venmo 打赏


---|---

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant