[Leetcode] 373. Find K Pairs with Smallest Sums 解题报告

来源:互联网 发布:电子商务发展数据2016 编辑:程序博客网 时间:2024/04/28 05:23

题目

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.

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

Example 1:

Given nums1 = [1,7,11], nums2 = [2,4,6],  k = 3Return: [1,2],[1,4],[1,6]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:

Given nums1 = [1,1,2], nums2 = [1,2,3],  k = 2Return: [1,1],[1,1]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:

Given nums1 = [1,2], nums2 = [3],  k = 3 Return: [1,3],[2,3]All possible pairs are returned from the sequence:[1,3],[2,3]

思路

1、基本版:暴力解法就是产生所有组合,然后按照和的大小排序,取最小的k个即可。这种时间复杂度是O((mn)log(mn)),空间复杂度是O(mn)。更好的一种解法是:定义一个数组,存储nums1中每个数字在nums2中对应的可以产生最小和的索引。这样每次我们扫描一遍nums1中的元素,就可以找出产生和最小的pair,将其加入结果集中之后,再增加对应索引即可。这种方法的空间复杂度是O(m),时间复杂度是O(km)。

2、改进版:在上面这个版本中,我们每次都要遍历一遍nums1。事实上,只要我们维护一个有序结构,还可以进一步改进时间复杂度。例如在下面这个改进版中,我们采用了multimap,其key是pair的和,value就是pair本身,这样我们每次可以在O(1)的时间内得到最小的pair,而删除和新增一个元素的时间复杂度都是O(logm)。这样就可以把时间复杂度进一步降低到O(mlogm + klogm)(事实上,如果我们采用heap或者priority_queue这种数据结构,还可以将时间复杂度降低到O(m + klogm),有兴趣的读者可以自行实现)。

代码

1、基本版:

class Solution {public:    vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {        int len1 = nums1.size(), len2 = nums2.size(), cnt = min(k, len1 * len2);        vector<int> index(len1, 0);             // indices in nums2 which will compose pairs in nums1        vector<pair<int, int>> ans;        while(cnt-- > 0) {            int tem_min = INT_MAX, m = 0;            for(int i = 0; i < len1; ++i) {     // find the minimum pair (nums1[i], nums2[index[i]])                if(index[i] < len2 && nums1[i] + nums2[index[i]] < tem_min) {                    tem_min = nums1[i] + nums2[index[i]];                    m = i;                }            }            ans.push_back(make_pair(nums1[m], nums2[index[m]++]));        }        return ans;    }};

2、改进版:

class Solution {public:    vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {        if(nums1.size() == 0 || nums2.size() == 0 || k == 0) {            return {};        }        multimap<int, pair<int, int>> mp;        vector<pair<int, int>> ans;        int len1 = nums1.size(), len2 = nums2.size();        for(int i = 0; i < len1; ++i) {     // the time complexity is O(mlogm)            mp.insert(make_pair(nums1[i] + nums2[0], make_pair(i, 0)));        }        int cnt = min(k, len1 * len2);        while(cnt-- > 0) {                  // the time complexity is O(klogm)            int idx1 = mp.begin()->second.first, idx2 = mp.begin()->second.second;            ans.push_back(make_pair(nums1[idx1], nums2[idx2]));            mp.erase(mp.begin());            if(idx2 + 1 < nums2.size()) {                mp.insert(make_pair(nums1[idx1] + nums2[idx2 + 1], make_pair(idx1, idx2 + 1)));            }        }        return ans;    }};

原创粉丝点击