LeetCode_Heap_373. Find K Pairs with Smallest Sums 查找和最小的K对数字 【堆】【C++/java】【中等】
2021/11/7 11:40:24
本文主要是介绍LeetCode_Heap_373. Find K Pairs with Smallest Sums 查找和最小的K对数字 【堆】【C++/java】【中等】,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
目录
一,题目描述
英文描述
中文描述
示例与说明
二,解题思路
三,AC代码
C++
Java
四,解题过程
第一博
第二搏
第三博
一,题目描述
英文描述
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.
中文描述
给定两个以升序排列的整数数组 nums1 和 nums2 , 以及一个整数 k 。
定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2 。
请找到和最小的 k 个数对 (u1,v1), (u2,v2) ... (uk,vk) 。
示例与说明
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-k-pairs-with-smallest-sums
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二,解题思路
java版本的代码采用小根堆,暴力双重循环,将所有组合依次放入堆中,最后筛选前k个;
- 上面的做法会超时,可以对部分条件进行筛选。由于只需要前k个最小组合,每个数组(nums1或nums2)中选出的数字个数不可能超过k(有k个小的不选,选大的?)。这样可以通过目前的测试用例。
C++版本采用大根堆,维持最小的k个组合,堆顶为最小k个组合中最大的一个。
- 当堆的大小达到k时,判断新组合与堆顶的优先级关系,若堆顶优先级高(说明堆顶的组合大于新组合),则将新组合放入堆中,并弹出堆顶。
三,AC代码
C++
class Solution { public: struct cmp { // 大根堆,维持k个最小值,堆顶为最小值中最大的一个 bool operator()(pair<int, int> a, pair<int, int> b) { return (a.first + a.second) < (b.first + b.second); } }; vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) { vector<vector<int>> ans; priority_queue<pair<int, int>, vector<pair<int, int>>, cmp> queue;// !!! for (int i = 0; i < nums1.size() && i < k; i++) { for (int j = 0; j < nums2.size() && j < k; j++) { if (queue.size() < k) { queue.push({nums1[i], nums2[j]}); } // 当堆顶的优先级大于新的数据时,将其加入到堆中 // 在这里直观的理解就是新数据小于堆顶,因此允许进入前k小 else if (cmp()({nums1[i], nums2[j]}, queue.top())) { queue.push({nums1[i], nums2[j]}); queue.pop(); } } } while (queue.size()) { ans.push_back({queue.top().first, queue.top().second}); queue.pop(); } return ans; } };
Java
class Solution { public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) { List<List<Integer>> ans = new ArrayList<>(); PriorityQueue<List<Integer>> queue = new PriorityQueue<>(new Comparator<>(){ public int compare(List<Integer> a, List<Integer> b) { return (b.get(0) + b.get(1)) - (a.get(0) + a.get(1)); } }); // 也可以这样写 // PriorityQueue<List<Integer>> queue = new PriorityQueue<>((a, b)->( // (b.get(0) + b.get(1) - a.get(0) - a.get(1)) // )); for (int i = 0; i < nums1.length && i < k; i++) { for (int j = 0; j < nums2.length && j < k; j++) { queue.offer(new ArrayList(Arrays.asList(nums1[i], nums2[j]))); if (queue.size() > k) queue.poll(); } } while (queue.size() > 0) { ans.add(queue.poll()); } return ans; } }
四,解题过程
第一博
借助优先队列——小根堆,双重循环将每一个可能的结果放进去,然后返回队列中的内容。
class Solution { public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) { List<List<Integer>> ans = new ArrayList<>(); PriorityQueue<List<Integer>> queue = new PriorityQueue<>(new Comparator<>(){ public int compare(List<Integer> a, List<Integer> b) { return (b.get(0) + b.get(1)) - (a.get(0) + a.get(1)); } }); for (int i = 0; i < nums1.length; i++) { for (int j = 0; j < nums2.length; j++) { queue.offer(new ArrayList(Arrays.asList(nums1[i], nums2[j]))); if (queue.size() > k) queue.poll(); } } while (queue.size() > 0) { ans.add(queue.peek()); queue.poll(); } return ans; } }
第二搏
上述解法和暴力解法基本差不多。现在考虑剪枝。
由于nums1和nums2是从小到大的排序数组,所以当双重循环中的指针(i 或 j )超过k时,就不需要继续计算下去了
第三博
换C++试一试大根堆的方法,直观来说就是维持一个大小为k的堆,堆中存放值最小的元素,这样堆顶就是最小k个元素中,最大的那一个。
当堆的大小达到k,可以将后面的元素与堆定比较,若小于堆顶(也就是堆顶优先级高,这里有点绕),则加入堆中成为前k小的一员,并弹出堆顶。
这篇关于LeetCode_Heap_373. Find K Pairs with Smallest Sums 查找和最小的K对数字 【堆】【C++/java】【中等】的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-04敏捷管理与看板工具:提升研发、设计、电商团队工作效率的利器
- 2025-01-04智慧养老管理工具如何重塑养老生态?
- 2025-01-04如何打造高绩效销售团队:工具与管理方法的结合
- 2025-01-04解决电商团队协作难题,在线文档工具助力高效沟通
- 2025-01-04春节超市管理工具:解锁高效运营与顾客满意度的双重密码
- 2025-01-046种主流销售预测模型:如何根据场景选用最佳方案
- 2025-01-04外贸服务透明化:增强客户信任与合作的最佳实践
- 2025-01-04重新定义电商团队协作:在线文档工具的战略作用
- 2025-01-04Easysearch Java SDK 2.0.x 使用指南(三)
- 2025-01-04百万架构师第八课:设计模式:设计模式容易混淆的几个对比|JavaGuide