力扣练习——19 查找和最小的K对数字

19 查找和最小的K对数字

1.问题描述
给定两个以升序排列的整形数组 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,5,7

解释: 返回序列中的前 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

输出: 2, 2

解释: 返回序列中的前 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],所以输出4, 5

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

可使用以下main函数:

int main()

{

int n,m,data,k;

vector<int> nums1,nums2;

cin>>n;

for(int i=0; i<n; i++)

{

    cin>>data;

    nums1.push_back(data);

}

cin>>m;

for(int i=0; i<m; i++)

{

    cin>>data;

    nums2.push_back(data);

}

cin>>k;

vector<vector<int> > res=Solution().kSmallestPairs(nums1,nums2,k);

for(int i=0; i<res.size(); i++)

{

    if (i>0)

        cout<<" ";

    cout<<res[i][0]+res[i][1];

}

return 0;

}
2.输入说明
首先输入nums1的长度n,然后输入n个整数

再输入nums2的长度m,然后输入m个整数

最后输入k

3.输出说明
按从小到大的顺序输出k对数字的和(注意:可能不足k对)
4.范例
输入
3
1 7 11
3
2 4 6
3
输出
3 5 7
5.代码

#include<iostream>
#include<queue>
#include<algorithm>
#include<map>
using namespace std;

class Solution
{

public:

    vector <vector<int>> kSmallestPairs(vector<int>&nums1, vector<int>&nums2, int k)
{
		//思想:利用优先队列实现小顶堆 ,nums1和nums2都是有序递增的
		//1.定义比较函数
		auto cmp = [&nums1, &nums2](const pair<int, int> & a, const pair<int, int> & b) {
			return nums1[a.first] + nums2[a.second] > nums1[b.first] + nums2[b.second];//注意这里是大于
		};
		//2.计算nums1和nums2长度
		int n = nums1.size();
		int m = nums2.size();
		vector<vector<int>> ans;//输出结果
		//3.定义优先级队列
		priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> pq(cmp);// decltype 是类型说明符,它的作用是选择并返回操作数的数据类型
		//4.避免元素重复插入问题 
		//将前 K个索引数对(0, 0), (1, 0),···,(k - 1, 0)(0, 0), (1, 0), …, (k−1, 0) 加入到队列中,每次从队列中取出元素(x, y)(x, y) 时,
		//我们只需要将nums2的索引增加即可,这样避免了重复加入元素的问题。
		for (int i = 0; i < min(k, n); i++) {
			pq.emplace(i, 0);//emplace_back能通过参数构造对象,不需要拷贝或者移动内存,相比push_back能更好地避免内存的拷贝与移动,使容器插入元素的性能得到进一步提升。
		}
		while (k-- > 0 && !pq.empty()) {
			auto x = pq.top().first;//auto存储在堆栈中,只有程序执行这些代码块时这种自动变量才会被创建,代码块执行结束后自动变量便被释放。
			auto y = pq.top().second;
			pq.pop();
			ans.emplace_back(initializer_list<int>{nums1[x], nums2[y]});//这里initializer_list<int>不能少
			//push_back()方法要调用构造函数和复制构造函数,这也就代表着要先构造一个临时对象,然后把临时的copy构造函数拷贝或者移动到容器最后面。
			//而emplace_back()在实现时,则是直接在容器的尾部创建这个元素,省去了拷贝或移动元素的过程。
			if (y + 1 < m) {
				pq.emplace(x, y + 1);//将nums2的索引递增
			}
		}

		return ans;

	
}
};



int main()

{

	int n, m, data, k;

	vector<int> nums1, nums2;

	cin >> n;

	for (int i = 0; i < n; i++)

	{

		cin >> data;

		nums1.push_back(data);

	}

	cin >> m;

	for (int i = 0; i < m; i++)

	{

		cin >> data;

		nums2.push_back(data);

	}

	cin >> k;

	vector<vector<int> > res = Solution().kSmallestPairs(nums1, nums2, k);

	for (int i = 0; i < res.size(); i++)

	{

		if (i > 0)

			cout << " ";

		cout << res[i][0] + res[i][1];

	}

	return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值