LeetCode-373 查找和最小的K对数字

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-k-pairs-with-smallest-sums

题目描述

给定两个以升序排列的整数数组 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

解题思路

根据提示,nums1和nums2数组的规模很大,所以全部求出所有数对的方法肯定第一个被否定,并且也没有必要求出所有的数对。

基本思路是使用记忆化的方法,将nums2中与nums1中配对的下标记录下来,减少重复计算。

从题目中可以得知,nums1和nums2都已经经过升序排序,那么对于最初情况来说,nums1[0] + nums2[0]必定为最小的数,对于第二小的数来说,他的候选最小数为num1[0] + nums2[1] 或者 nums1[1] + nums[2]。对于一般情况第k小的数,他的候选数为nums1[0] + nums2[i0]、nums1[1] + nums2[i1]、nums1[2] + nums2[i2]……nums1[j] + nums2[ij]、nums1[j + 1] + nums2[0],其中j是之前遍历访问过的num1的下标最大值,ij 是对于nums2 中未与nums1[i]配对过的下标最小值,这里可以用一个vector来记录。由于nums2是升序的,所以nums1[j + 1] + nums2[0] 肯定比 nums1[j + m] + nums2[n] 小,之后的数肯定不属于第k个最小数。

代码展示

复制代码
class Solution {
public:
    vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
        int iIndex1 = 0, iIndex2 = 0, iCount = 0;
        vector<vector<int>> vviRet;
        vector<int> viJIndex;
        viJIndex.push_back(0);
        while(iCount < k && iCount < nums1.size() * nums2.size())
        {
            int min = INT_MAX;
            iCount++;
            for(int i = 0; i < viJIndex.size(); i++)
            {
                if(viJIndex[i] != -1 && nums1[i] + nums2[viJIndex[i]] < min)
                {
                    min = nums1[i] + nums2[viJIndex[i]];
                    iIndex1 = i;
                    iIndex2 = viJIndex[i];
                }
            }
            if(viJIndex.size() < nums1.size() && nums1[viJIndex.size()] + nums2[0] < min)
            {
                iIndex1 = viJIndex.size();
                iIndex2 = 0;
                viJIndex.push_back(0);
            }
            viJIndex[iIndex1]++;
            if(viJIndex[iIndex1] >= nums2.size())
            {
                viJIndex[iIndex1] = -1;
            }
            vviRet.push_back({nums1[iIndex1], nums2[iIndex2]});
        }
        return vviRet;
    }
};
复制代码

 

运行结果

 

posted @   过客匆匆,沉沉浮浮  阅读(78)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示