--- title: 373. Find K Pairs with Smallest Sums tags: leetcode disqus: foodtoothshackmd --- https://leetcode.com/problems/find-k-pairs-with-smallest-sums/ ## Idea We can sort all of them in a priority_queue and pick. ### Smart one 由于全量的排序操作,元素移位操作等损耗很大。针对这$m \times n$对数的排列(这个矩阵),可以直接考虑出方法找出当前候选值中的小值,然后往复到结束条件。 ## Code ### Straight forward ```cpp class Solution { public: vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) { auto cmp = [](const std::vector<int>& left, const std::vector<int>& right) { return left.front() + left.back() < right.front() + right.back(); }; std::priority_queue<std::vector<int>, std::vector<std::vector<int>>, decltype(cmp)> pq(cmp); for (int i{}; i < nums1.size(); ++i) { for (int j{}; j < nums2.size(); ++j) { pq.emplace((std::initializer_list<int>){nums1[i], nums2[j]}); if (pq.size() > k) pq.pop(); } } std::vector<std::vector<int>> result; while (!pq.empty()) { result.push_back(pq.top()); pq.pop(); } return result; } }; ``` ### Smart one ```cpp class Solution { public: vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) { int nums1_size = nums1.size(); int nums2_size = nums2.size(); std::vector<std::vector<int>> result{}; if (nums1_size == 0 || nums2_size == 0) return result; // Comparision func for cands(extract index from tuple and compare sum) auto cmp = [&nums1, &nums2](auto left, auto right) { return nums1[std::get<0>(left)] + nums2[std::get<1>(left)] > nums1[std::get<0>(right)] + nums2[std::get<1>(right)]; }; std::priority_queue<std::tuple<int, int>, std::vector<std::tuple<int, int>>, decltype(cmp)> cands(cmp); // Checkers are used to check whether there is smaller one already in cands std::vector<bool> x_checker(nums1_size, false); std::vector<bool> y_checker(nums2_size, false); int x{}, y{}; while (true) { if (k == 0 || (x + 1 == nums1_size && y + 1 == nums2_size)) { return result; } // Handle first-one condition if (cands.empty()) { cands.emplace(x, y); x_checker[x] = true; y_checker[y] = true; } // Get current smallest sum one std::tie(x, y) = cands.top(); cands.pop(); x_checker[x] = false; y_checker[y] = false; result.emplace_back(std::initializer_list<int>{nums1[x], nums2[y]}); --k; // Push new candidates according to popped one if (x + 1 < nums1_size && !x_checker[x + 1]) { cands.emplace(x + 1, y); x_checker[x + 1] = true; y_checker[y] = true; } if (y + 1 < nums2_size && !y_checker[y + 1]) { cands.emplace(x, y + 1); x_checker[x] = true; y_checker[y + 1] = true; } } } }; ```