Find K Pairs with Smallest Sums 查找和最小的K对数字

给定两个以升序排列的整形数组 nums1 和 nums2, 以及一个整数 k

定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2

找到和最小的 k 对数字 (u1,v1), (u2,v2) ... (uk,vk)

示例 1:

给出: nums1 = [1,7,11], nums2 = [2,4,6],  k = 3

返回: [1,2],[1,4],[1,6]

返回序列中的前 3 对数:
[1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6]

示例 2:

给出:nums1 = [1,1,2], nums2 = [1,2,3],  k = 2

返回: [1,1],[1,1]

返回序列中的前 2 对数:
[1,1],[1,1],[1,2],[2,1],[1,2],[2,2],[1,3],[1,3],[2,3]

示例 3:

给出:nums1 = [1,2], nums2 = [3],  k = 3 

返回: [1,3],[2,3]

也可能序列中所有的数对都被返回:
[1,3],[2,3]

思路一:直接创建vector<int,int> res的变量,遍历nums1和nums2的所有组合,只不过在vector内部的排序算法改成自定义的根据和进行排序的算法。

参考代码:

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

思路二:使用multimap(键可重复),其排序也是自定义算法,最后放到res中。

参考代码:

class Solution {
public:
    vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
	vector<pair<int, int>> res;
	multimap<int, pair<int, int>> m;
	for (int i = 0; i < nums1.size(); i++) {
		for (int j = 0; j < nums2.size(); j++) {
			m.insert({ nums1[i] + nums2[j],{nums1[i],nums2[j]} });
		}
	}
	for (auto it = m.begin(); it != m.end(); it++) {
		res.push_back(it->second);
		if (--k <= 0) return res;
	}
	return res;   
    }
};

思路三:本来前两种算法就够了,主要是看到提交的时间实在是令人捉急,并且这道题的tag是堆,目前还没有用到堆呢,对于用堆来解题思路和上面一样,不过这里要想清楚是用最大堆还是最小堆,直觉既然是找最小的值,那么肯定是最小堆了。用最小堆也可以解,我们来看如何用最大堆来解题,我们保证堆里的元素只有k个且堆顶是最大值,那么如果有一个较小的组合进来了,就压入小组合,弹出堆顶元素(这时最大的值被弹出了,剩下的都是较小的,以此类推可以得到最小的k个组合),但是要注意这时堆顶的元素依然是最小的k个组合的最大的组合。

参考代码:

class Solution {
public:
struct cmp {
	bool operator ()(pair<int, int> &a, pair<int, int> &b) {
		return (a.first + a.second) < (b.first + b.second);
	}
};
vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
	vector<pair<int, int>> res;
	priority_queue<pair<int, int>, vector<pair<int, int>>, cmp> heap;
	for (int i = 0; i < nums1.size(); i++) {
		for (int j = 0; j < nums2.size(); j++) {
			if (heap.size() < k) heap.push({ nums1[i],nums2[j] });
			else {
				if ((nums1[i] + nums2[j]) < (heap.top().first + heap.top().second)) {
					heap.push({ nums1[i],nums2[j] }); 
					heap.pop();
				}
			}
		}
	}
	while (!heap.empty()) {
		res.push_back(heap.top()); heap.pop();
	}
	return res;
}
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值