给定两个以升序排列的整数数组 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]
结题思路:题目要求返回一个List<List<Integer>>数据类型 结果,首先我们得new一个List<List<Integer>>这样的数据类型,然后建立一个大小为k大堆,为什么建立大堆呢?因为大堆在进行筛选的时候可以通过top的值来判定新值是否能入堆,只要是比top值小的组合,就能进入堆,进入堆的数据就是我们需要的数据。那怎么来比较一组数据的大小呢?
思路先把所有对应的List一次放入一个大堆中,当堆的大小小于k,直接放入堆中, 当放满了之后,接着放入元素的时候要判断堆顶元素和放入元的大小,要是放入的元素比堆顶元素小的话,就直接把堆顶元素 抛出,最后把该元素插入到堆中。
PriorityQueue<List<Integer>> priorityQueue = new PriorityQueue<>(k, new Comparator<List<Integer>>() { @Override public int compare(List<Integer> o1, List<Integer> o2) { return ((o2.get(0) + o2.get(1)) - (o1.get(0) + o1.get(1))); } });
这是是写一个大小为k的大堆,为什么是大堆呢,因为重写了compare方法,方法返回值是List<Integer>中下标为0和1的值之差,o1代表堆顶元素,o2代表新增元素。
整体代码及解题思路详解
public static List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) { //思路:先把所有对应的List一次放入一个大堆中,当堆的大小小于k,直接放入堆中, //当放满了之后,接着放入元素的时候要判断堆顶元素和放入元的大小,要是放入的元素比堆顶元素小的话,就直接把堆顶元素 //抛出,最后把该元素插入到堆中 List<List<Integer>> lists = new ArrayList<>(); PriorityQueue<List<Integer>> priorityQueue = new PriorityQueue<>(k, new Comparator<List<Integer>>() { @Override public int compare(List<Integer> o1, List<Integer> o2) { return ((o2.get(0) + o2.get(1)) - (o1.get(0) + o1.get(1))); } }); //遍历num1的数组元素 for (int i = 0; i < nums1.length; i++) { //遍历num2的数组元素 for (int j = 0; j < nums2.length; j++) { //当堆未放满的时候,直接往堆里面插入数据类型为List<Integer>的数据 if (priorityQueue.size() < k) { //构造List<Integer>类型的数据 List<Integer> list = new ArrayList<>(); //将num1[i]和num2[j]加入list中 list.add(nums1[i]); list.add(nums2[j]); //最后将list加入堆中 priorityQueue.offer(list); } else { //当堆已经放满了时,这时候需要拿出堆顶元素与新的元素的值进行比较 //拿出堆顶元素 List<Integer> top = priorityQueue.peek(); //堆顶元素的值 int topVal = top.get(0) + top.get(1); //当堆顶的值大于新的值,就要把堆顶的元素poll出去,然后把新的元素offer进来 if (topVal > nums1[i] + nums2[j]) { //达成条件,poll堆顶元素的值 priorityQueue.poll(); List<Integer> list = new ArrayList<>(); list.add(nums1[i]); list.add(nums2[j]); //把新的值入堆 priorityQueue.offer(list); } } } } //打印堆中的元素,判断条件有:打印次数首先要小于或等于k,且堆不为空才能输出 for (int i = 0; i < k && !priorityQueue.isEmpty(); i++) { System.out.println(priorityQueue.peek()); lists.add(priorityQueue.poll()); } //返回堆 return lists; }