算法经典题:查找和最小的 K 对数字

LeetCode373.查找和最少的K对数字

给定两个以 升序排列 的整数数组nums1nums2, 以及一个整数k

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

请找到和最小的k个数对(u_1,v_1), (u_2,v_2) ... (u_k,v_k)

提示:

  • 1 <= nums1.length, nums2.length <= 10^5
  • -10^9 <= nums1[i], nums2[i] <= 10^9
  • nums1nums2均为升序排列
  • 1 <= k <= 1000

思路

n=nums1.lengthm=nums2.length。那么总共可以组成nm对数。因为两个数组有序。所以以下各个数对的和也是有序的。

\\nums1[0]+nums2[0],nums1[1]+nums2[0],...,nums1[n-1]+nums2[0]\\ nums1[0]+nums2[1],nums1[1]+nums2[1],...,nums1[n-1]+nums2[1]\\ ...\\ nums1[0]+nums2[m-1],nums1[1]+nums2[m-1],...,nums1[n-1]+nums2[m-1]

所以可以使用优先队列(小根堆)存每行的第一个数对和,每次弹出队首元素必然就是当前最小值,并将该行的下一个数对和存入优先队列即可。

Java代码如下:

class Solution {
    public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
        List<List<Integer>> res = new ArrayList<>();
        PriorityQueue<int[]> q = new PriorityQueue<>((a,b) -> a[0] - b[0]);
        int n = nums1.length, m = nums2.length;
        for(int i = 0;i < m;i++) {
            q.offer(new int[]{nums1[0] + nums2[i], 0 ,i});
        }
        while(q.size() > 0 && res.size() < k) {
            int[] p = q.poll();
            List<Integer> list = new ArrayList<>();
            list.add(nums1[p[1]]);
            list.add(nums2[p[2]]);
            res.add(list);
            if(p[1] + 1 < n) {
                q.offer(new int[]{nums1[p[1]+1]+nums2[p[2]], p[1] + 1, p[2]});
            }
        }
        return res;
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值