Before attempting this problem, you should be comfortable with:
The most direct approach computes all possible products by multiplying each element in the first array with each element in the second. After generating all products, we sort them and return the k-th smallest. While simple, this requires O(m * n) space and time for generation, plus O(m * n * log(m * n)) for sorting, making it impractical for large inputs.
nums1, multiply it with each element in nums2 and add to the list.k - 1.Where and are the lengths of the arrays and , respectively.
Instead of enumerating all products, we can binary search on the answer. For a candidate product value, we count how many products are less than or equal to it. If the count is less than k, we need a larger product; otherwise, we search smaller. The counting function leverages the sorted nature of both arrays: for positive numbers in nums1, we use upper bound on nums2; for negative numbers, we use lower bound with adjusted logic.
-10^10 to 10^10 (product bounds).k products are less than or equal to it.prod:a in nums1: count elements in nums2 where a * b <= prod.a: count elements where the product doesn't exceed prod (direction reverses).a = 0: if prod >= 0, all of nums2 contributes.class Solution:
def kthSmallestProduct(self, nums1: List[int], nums2: List[int], k: int) -> int:
def count(prod):
cnt = 0
n2 = len(nums2)
for a in nums1:
if a > 0:
cnt += bisect.bisect_right(nums2, prod // a)
elif a < 0:
threshold = math.ceil(prod / a)
idx = bisect.bisect_left(nums2, threshold)
cnt += n2 - idx
else:
if prod >= 0:
cnt += n2
return cnt
l, r = -(10**10), 10**10
while l <= r:
m = l + (r - l) // 2
if count(m) < k:
l = m + 1
else:
r = m - 1
return lWhere and are the lengths of the arrays and , respectively. is the size of the range of the product.
We can optimize the counting step using two pointers instead of binary search for each element. By separating negative and non-negative numbers in both arrays, we handle four cases: negative times negative (positive result), positive times positive, negative times positive, and positive times negative. For each case, two pointers can efficiently count products less than or equal to the target by exploiting monotonicity.
pos1, pos2).nums1 with negatives from nums2 (yields positives).nums1 with positives from nums2.nums1 with positives from nums2 (yields negatives).nums1 with negatives from nums2.k.class Solution:
def kthSmallestProduct(self, nums1: List[int], nums2: List[int], k: int) -> int:
n1, n2 = len(nums1), len(nums2)
pos1 = 0 # first non-negative in nums1
while pos1 < n1 and nums1[pos1] < 0:
pos1 += 1
pos2 = 0 # first non-negative in nums2
while pos2 < n2 and nums2[pos2] < 0:
pos2 += 1
def count(prod):
cnt = 0
# negative * negative -> positive
i, j = 0, pos2 - 1
while i < pos1 and j >= 0:
if nums1[i] * nums2[j] > prod:
i += 1
else:
cnt += (pos1 - i)
j -= 1
# positive * positive -> positive
i, j = pos1, n2 - 1
while i < n1 and j >= pos2:
if nums1[i] * nums2[j] > prod:
j -= 1
else:
cnt += (j - pos2 + 1)
i += 1
# negative * positive -> negative
i, j = 0, pos2
while i < pos1 and j < n2:
if nums1[i] * nums2[j] > prod:
j += 1
else:
cnt += (n2 - j)
i += 1
# positive * negative → negative
i, j = pos1, 0
while i < n1 and j < pos2:
if nums1[i] * nums2[j] > prod:
i += 1
else:
cnt += (n1 - i)
j += 1
return cnt
left, right = -10**10, 10**10
while left <= right:
mid = (left + right) // 2
if count(mid) < k:
left = mid + 1
else:
right = mid - 1
return leftWhere and are the lengths of the arrays and , respectively. is the size of the range of the product.
Products of two integers can exceed the 32-bit integer range, especially when values approach 10^5 in magnitude. Always use 64-bit integers (long long in C++, long in Java) for product calculations and comparisons. Failing to do so causes incorrect counts and wrong answers.
When one or both arrays contain negative numbers, the sign of the product flips, and the ordering reverses. A negative number multiplied by a large positive yields a more negative (smaller) result. You must handle negative-negative, negative-positive, positive-negative, and positive-positive cases separately to count products correctly.
Standard integer division truncates toward zero, but counting products requires floor division for positive divisors and ceiling logic for negative divisors. Using the wrong rounding direction causes off-by-one errors in binary search bounds. Use language-specific floor division functions or manually adjust for negative operands.
When an element is zero, its product with any number is zero. This affects counting: if the target product is non-negative, all pairs involving zero contribute to the count. Forgetting to handle zeros separately leads to missing or double-counting products.
The search range must cover all possible products, from the most negative to the most positive. Setting bounds too tight causes the algorithm to miss the answer. Use safe bounds like -10^10 to 10^10 based on the problem constraints, and ensure the binary search condition correctly finds the smallest value with at least k products less than or equal to it.