Before attempting this problem, you should be comfortable with:
We need to select exactly k indices. The score is the sum of selected elements from nums1 multiplied by the minimum of selected elements from nums2. Since we must choose exactly k elements, we can use recursion to try all combinations: for each index, either include it or skip it. When we include an element, we update the running sum and track the minimum from nums2.
k, current minimum from nums2, and current sum from nums1.k == 0, return sum * minVal.k more elements, return negative infinity.minVal is 0, the result is 0 (any selection will have score 0).class Solution:
def maxScore(self, nums1: List[int], nums2: List[int], k: int) -> int:
n = len(nums1)
def dfs(i, k, minVal, curSum):
if k == 0:
return curSum * minVal
if i == n or (n - i) < k:
return float("-inf")
if minVal == 0:
return 0
res = dfs(i + 1, k, minVal, curSum)
res = max(res, dfs(i + 1, k - 1, min(minVal, nums2[i]), curSum + nums1[i]))
return res
return dfs(0, k, float("inf"), 0)The key insight is that if we fix which element provides the minimum from nums2, we want the k largest corresponding values from nums1 (among elements with nums2 values >= our minimum). By sorting pairs by nums2 in descending order and processing them one by one, each new element becomes the new minimum. We maintain the k largest nums1 values seen so far using a min-heap.
(nums1[i], nums2[i]) and sort by nums2 in descending order.k largest nums1 values seen so far.nums1 value to the heap and update the sum.k, remove the smallest and subtract from sum.k, calculate score (sum * current nums2) and update result.class Solution:
def maxScore(self, nums1: List[int], nums2: List[int], k: int) -> int:
pairs = sorted(zip(nums1, nums2), key=lambda p: p[1], reverse=True)
minHeap = []
n1Sum = 0
res = 0
for n1, n2 in pairs:
n1Sum += n1
heapq.heappush(minHeap, n1)
if len(minHeap) > k:
n1Sum -= heapq.heappop(minHeap)
if len(minHeap) == k:
res = max(res, n1Sum * n2)
return resThis is a space-optimized version that packs both values into a single 64-bit integer. Since the problem constraints allow values up to 10^5, we can use bit shifting to combine nums2 (upper bits) and nums1 (lower bits). Sorting these combined values gives us the same ordering as sorting by nums2, and we can extract both values using bitwise operations.
(nums2[i] << 30) | nums1[i].nums2 primarily).nums1 and nums2 using bit operations.nums1 to heap and sum; remove smallest if heap exceeds k.k elements, calculate and track maximum score.class Solution:
def maxScore(self, nums1: List[int], nums2: List[int], k: int) -> int:
n = len(nums1)
arr = [(nums2[i] << 30) | nums1[i] for i in range(n)]
arr.sort(reverse=True)
minHeap = []
n1Sum = 0
res = 0
for num in arr:
n1, n2 = num & ((1 << 30) - 1), num >> 30
n1Sum += n1
heapq.heappush(minHeap, n1)
if len(minHeap) > k:
n1Sum -= heapq.heappop(minHeap)
if len(minHeap) == k:
res = max(res, n1Sum * n2)
return resTo maximize the sum of k elements from nums1, you need to keep the k largest values seen so far. This requires a min-heap so you can efficiently remove the smallest element when the heap exceeds size k. Using a max-heap makes it impossible to efficiently evict the smallest element, leading to incorrect tracking of the top k values.
The algorithm relies on processing elements in decreasing order of nums2 values so that each new element becomes the new minimum. If you sort in ascending order or forget to sort entirely, the minimum tracking breaks and the score calculation becomes incorrect.
When the heap size exceeds k and you pop the smallest element, you must also subtract that element's value from your running sum. Forgetting to update the sum after removal causes it to include values no longer in the heap, producing inflated and incorrect scores.