LeetCode练习2040

该博客介绍了如何解决寻找两个有序数组中第k小乘积的问题。首先,作者尝试了暴力求解方法,即通过遍历数组并计算所有乘积进行排序,但这种方法在数据规模较大时会导致超时。接着,作者提出了一种更高效的解决方案,通过分类讨论和二分查找减少循环次数,实现了在大数据集上的高效计算。这种方法能够有效处理两个有序数组中元素的乘积,并找到第k小的乘积值。
摘要由CSDN通过智能技术生成

给你两个 从小到大排好序 且下标从 0 开始的整数数组 nums1 和 nums2 以及一个整数 k ,请你返回第 k (从 1 开始编号)小的 nums1[i] * nums2[j] 的乘积,其中 0 <= i < nums1.length 且 0 <= j < nums2.length 。
 

示例 1:

输入:nums1 = [2,5], nums2 = [3,4], k = 2
输出:8
解释:第 2 小的乘积计算如下:
- nums1[0] * nums2[0] = 2 * 3 = 6
- nums1[0] * nums2[1] = 2 * 4 = 8
第 2 小的乘积为 8 。
示例 2:

输入:nums1 = [-4,-2,0,3], nums2 = [2,4], k = 6
输出:0
解释:第 6 小的乘积计算如下:
- nums1[0] * nums2[1] = (-4) * 4 = -16
- nums1[0] * nums2[0] = (-4) * 2 = -8
- nums1[1] * nums2[1] = (-2) * 4 = -8
- nums1[1] * nums2[0] = (-2) * 2 = -4
- nums1[2] * nums2[0] = 0 * 2 = 0
- nums1[2] * nums2[1] = 0 * 4 = 0
第 6 小的乘积为 0 。
示例 3:

输入:nums1 = [-2,-1,0,1,2], nums2 = [-3,-1,2,4,5], k = 3
输出:-6
解释:第 3 小的乘积计算如下:
- nums1[0] * nums2[4] = (-2) * 5 = -10
- nums1[0] * nums2[3] = (-2) * 4 = -8
- nums1[4] * nums2[0] = 2 * (-3) = -6
第 3 小的乘积为 -6 。
 

提示:

1 <= nums1.length, nums2.length <= 5 * 104
-105 <= nums1[i], nums2[j] <= 105
1 <= k <= nums1.length * nums2.length
nums1 和 nums2 都是从小到大排好序的。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/kth-smallest-product-of-two-sorted-arrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一想法:将num1数组最小值分别与num2数组的数相乘,将这些值存入sub数组,然后对sub数组来一次冒泡排序(就是最简单的暴力破解。。)

long long kthSmallestProduct(int* nums1, int nums1Size, int* nums2, int nums2Size, long long k){//数据集一大起来就TLE了。。
    int a=nums2Size*nums1Size;
    long long sub[a];
    int m=0;
    for(int i=0;i<nums1Size;i++){
        for(int j=0;j<nums2Size;j++){
                    sub[m]= (long long)nums1[i] * nums2[j];
                    m++;
        }
    }
    for(int n=0;n<a-1;n++){
        for(int p=0;p<a-n-1;p++){
            if(sub[p]>sub[p+1]){
                long long  swap;
                swap=sub[p+1];
                sub[p+1]=sub[p];
                sub[p]=swap;
            }
        }
    }
    return (long long) sub[k-1];
}

不出意外。。

然后只能考虑一种循环少点的写法了。。比如分类讨论

 

long long kthSmallestProduct(vector<int>& nums1, vector<int>& nums2, long long k) {
        vector<int> neg1, pos1, neg2, pos2;
        for(int v : nums1) (v < 0)? neg1.push_back(v) : pos1.push_back(v);
        for(int v : nums2) (v < 0)? neg2.push_back(v) : pos2.push_back(v);

        long long l = -1e10, r = 1e10;
        while(l < r) {
            long long m = (l + r) >> 1;//>>是右移一次,相当于/2,后面的参数是移位次数,m初始0
            long long cur = 0;
            for(int i = 0, j = (int)pos2.size() - 1; i < pos1.size(); ++i) {
                while(j >= 0 && 1ll * pos1[i] * pos2[j] > m) --j;//ill是将这个数转化为long long类型的参数
                cur += j + 1;//找到满足k的
            }
            for(int i = 0, j = 0; i < neg1.size(); ++i) {
                while(j < pos2.size() && 1ll * neg1[i] * pos2[j] > m) ++j;
                cur += (int)pos2.size() - j;
            }
            for(int i = 0, j = 0; i < pos1.size(); ++i) {
                while(j < neg2.size() && 1ll * pos1[i] * neg2[j] <= m) ++j;
                cur += j;
            }
            for(int i = 0, j = (int)neg2.size() - 1; i < neg1.size(); ++i) {
                while(j >= 0 && 1ll * neg1[i] * neg2[j] <= m) --j;
                cur += (int)neg2.size() - 1 - j;
            }
            if(cur < k) l = m + 1;
            else r = m;
        }

        return l;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值