LeetCode 题解工作台

两个有序数组的第 K 小乘积

给你两个 从小到大排好序 且下标从 0 开始的整数数组 nums1 和 nums2 以及一个整数 k ,请你返回第 k (从 1 开始编号)小的 nums1[i] \* nums2[j] 的乘积,其中 0 且 0 。 示例 1: 输入: nums1 = [2,5], nums2 = [3,4], k…

category

2

题型

code_blocks

6

代码语言

hub

3

相关题

当前训练重点

困难 · 二分·搜索·答案·空间

bolt

答案摘要

我们可以二分枚举乘积的值 ,定义二分的区间为 $[l, r]$,其中 $l = -\textit{max}(|\textit{nums1}[0]|, |\textit{nums1}[n - 1]|) \times \textit{max}(|\textit{nums2}[0]|, |\textit{nums2}[n - 1]|)$, $r = -l$。 对于每个 ,我们计算出乘积小于等于 的乘积…

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 二分·搜索·答案·空间 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

给你两个 从小到大排好序 且下标从 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 都是从小到大排好序的。
lightbulb

解题思路

方法一:二分查找

我们可以二分枚举乘积的值 pp,定义二分的区间为 [l,r][l, r],其中 l=max(nums1[0],nums1[n1])×max(nums2[0],nums2[n1])l = -\textit{max}(|\textit{nums1}[0]|, |\textit{nums1}[n - 1]|) \times \textit{max}(|\textit{nums2}[0]|, |\textit{nums2}[n - 1]|), r=lr = -l

对于每个 pp,我们计算出乘积小于等于 pp 的乘积的个数,如果这个个数大于等于 kk,那么说明第 kk 小的乘积一定小于等于 pp,我们就可以将区间右端点缩小到 pp,否则我们将区间左端点增大到 p+1p + 1

那么问题的关键就是如何计算乘积小于等于 pp 的乘积的个数。我们可以枚举 nums1\textit{nums1} 中的每个数 xx,分类讨论:

  • 如果 x>0x > 0,那么 x×nums2[i]x \times \textit{nums2}[i] 随着 ii 的增大是单调递增的,我们可以使用二分查找找到最小的 ii,使得 x×nums2[i]>px \times \textit{nums2}[i] > p,那么 ii 就是小于等于 pp 的乘积的个数,累加到个数 cnt\textit{cnt} 中;
  • 如果 x<0x < 0,那么 x×nums2[i]x \times \textit{nums2}[i] 随着 ii 的增大是单调递减的,我们可以使用二分查找找到最小的 ii,使得 x×nums2[i]px \times \textit{nums2}[i] \leq p,那么 nin - i 就是小于等于 pp 的乘积的个数,累加到个数 cnt\textit{cnt} 中;
  • 如果 x=0x = 0,那么 x×nums2[i]=0x \times \textit{nums2}[i] = 0,如果 p0p \geq 0,那么 nn 就是小于等于 pp 的乘积的个数,累加到个数 cnt\textit{cnt} 中。

这样我们就可以通过二分查找找到第 kk 小的乘积。

时间复杂度 O(m×logn×logM)O(m \times \log n \times \log M),其中 mmnn 分别为 nums1\textit{nums1}nums2\textit{nums2} 的长度,而 MMnums1\textit{nums1}nums2\textit{nums2} 中的最大值的绝对值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution:
    def kthSmallestProduct(self, nums1: List[int], nums2: List[int], k: int) -> int:
        def count(p: int) -> int:
            cnt = 0
            n = len(nums2)
            for x in nums1:
                if x > 0:
                    cnt += bisect_right(nums2, p / x)
                elif x < 0:
                    cnt += n - bisect_left(nums2, p / x)
                else:
                    cnt += n * int(p >= 0)
            return cnt

        mx = max(abs(nums1[0]), abs(nums1[-1])) * max(abs(nums2[0]), abs(nums2[-1]))
        return bisect_left(range(-mx, mx + 1), k, key=count) - mx
speed

复杂度分析

指标
时间O((n_1 + n_2)\log C)
空间O(1)
psychology

面试官常问的追问

外企场景
  • question_mark

    Binary search over the valid product range indicates efficiency over brute force enumeration.

  • question_mark

    Handling negative and positive products separately tests problem decomposition skills.

  • question_mark

    Expect questions about counting pairs without generating all products.

warning

常见陷阱

外企场景
  • error

    Forgetting to split counting logic for negative, zero, and positive numbers causes incorrect results.

  • error

    Assuming all products are positive may miscount the kth smallest for mixed-sign arrays.

  • error

    Not handling large input ranges efficiently can exceed time limits.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Finding the kth largest product instead of smallest requires reversing comparison logic.

  • arrow_right_alt

    Arrays not sorted require initial sorting, increasing time complexity to O(n log n) per array.

  • arrow_right_alt

    Finding kth smallest sum instead of product changes counting and case handling.

help

常见问题

外企场景

两个有序数组的第 K 小乘积题解:二分·搜索·答案·空间 | LeetCode #2040 困难