0
点赞
收藏
分享

微信扫一扫

剑指 Offer II 061. 和最小的 k 个数对(中等 堆 数组)

登高且赋 2022-03-11 阅读 48

剑指 Offer II 061. 和最小的 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]

提示:

1 <= nums1.length, nums2.length <= 104
-109 <= nums1[i], nums2[i] <= 109
nums1, nums2 均为升序排列
1 <= k <= 1000

分析

方法一:最大堆
时间复杂度O(k2logk)。
利用最大堆,最大堆储存int[]类型,按照数组中两个数的和从大到小排列。
遍历两个数组将前k个最小数对存到最大堆中,最后遍历最大堆存储到list里。
方法二:最小堆
时间复杂度O(klogk)。
利用最小堆,每次获得最小值。最小堆存储int[]类型,数组的第一个数是nums1数组的索引,第二个数是nums2数组的索引,按照两个索引对应数字之和排序。
首先固定nums2的索引0,遍历nums1小于等于k的索引,存储到最小堆中,然后遍历nums2的索引,同时保存最小堆堆顶的索引对应的值到答案中。存够k个或者遍历完数组最后输出即可。

题解(Java)

方法一:

class Solution {
    public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
        Queue<int[]> maxHeap = new PriorityQueue<>((i1, i2) -> i2[0] + i2[1] - i1[0] - i1[1]);
        for (int i = 0; i < Math.min(nums1.length, k); i++) {
            for (int j = 0; j < Math.min(nums2.length, k); j++) {
                if (maxHeap.size() >= k) {
                    int[] record = maxHeap.peek();
                    if (record[0] + record[1] > nums1[i] + nums2[j]) {
                        maxHeap.poll();
                        maxHeap.offer(new int[] {nums1[i], nums2[j]});
                    }
                } else {
                    maxHeap.offer(new int[] {nums1[i], nums2[j]});
                }
            }
        }
        List<List<Integer>> ans = new ArrayList<>();
        while (!maxHeap.isEmpty()) {
            int[] vals = maxHeap.poll();
            ans.add(Arrays.asList(vals[0], vals[1]));
        }
        return ans;
    }
}

方法二:

class Solution {
    public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
        Queue<int[]> minHeap = new PriorityQueue<>((i1, i2) -> nums1[i1[0]] + nums2[i1[1]] - nums1[i2[0]] - nums2[i2[1]]);
        for (int i = 0; i < Math.min(nums1.length, k); i++) {
            minHeap.offer(new int[] {i, 0});
        }
        List<List<Integer>> ans = new ArrayList<>();
        while (k-- > 0 && !minHeap.isEmpty()) {
            int[] record = minHeap.poll();
            ans.add(Arrays.asList(nums1[record[0]], nums2[record[1]]));
            if (record[1] < nums2.length - 1) minHeap.offer(new int[] {record[0], ++record[1]});
        }
        return ans;
    }
}
举报

相关推荐

0 条评论