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

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 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;
    }
};


运行结果

 

相关文章
|
7月前
|
存储 算法
LeetCode刷题---209. 长度最小的子数组(双指针-滑动窗口)
LeetCode刷题---209. 长度最小的子数组(双指针-滑动窗口)
|
7月前
|
算法 测试技术 C++
二分查找|滑动窗口|前缀和|LeetCode209: 长度最小的子数组
二分查找|滑动窗口|前缀和|LeetCode209: 长度最小的子数组
|
7月前
剑指Offer LeetCode 面试题40. 最小的k个数
剑指Offer LeetCode 面试题40. 最小的k个数
36 0
|
7月前
|
Java C++ Python
leetcode-209:长度最小的子数组
leetcode-209:长度最小的子数组
46 0
|
机器学习/深度学习 算法
代码随想录Day02 数组基础2 leetcode T977有序数组的平方, T209 长度最小的子数组,T59 螺旋矩阵II
代码随想录Day02 数组基础2 leetcode T977有序数组的平方, T209 长度最小的子数组,T59 螺旋矩阵II
59 0
|
6月前
|
算法 测试技术 程序员
力扣经典150题第三十题:长度最小的子数组
力扣经典150题第三十题:长度最小的子数组
30 1
|
6月前
|
存储
力扣-2904最短且字典序最小的美丽子序列
力扣-2904最短且字典序最小的美丽子序列
38 1
|
7月前
|
人工智能
力扣100114. 元素和最小的山形三元组 II(中等)
力扣100114. 元素和最小的山形三元组 II(中等)
|
6月前
【LeetCode刷题】滑动窗口思想解决问题:长度最小的子数组、无重复字符的最长子串
【LeetCode刷题】滑动窗口思想解决问题:长度最小的子数组、无重复字符的最长子串
|
7月前
【力扣】209. 长度最小的子数组
【力扣】209. 长度最小的子数组