Maximum Subsequence Score
MedPrompt
You are given two 0-indexed integer arrays nums1 and nums2 of equal length n and a positive integer k. You must choose a subsequence of indices from nums1 of length k.
For chosen indices i0, i1, ..., ik - 1, your score is defined as:
- The sum of the selected elements from
nums1multiplied with the minimum of the selected elements fromnums2. - It can defined simply as:
(nums1[i0] + nums1[i1] +...+ nums1[ik - 1]) * min(nums2[i0] , nums2[i1], ... ,nums2[ik - 1]).
Return the maximum possible score.
A subsequence of indices of an array is a set that can be derived from the set {0, 1, ..., n-1} by deleting some or no elements.
Example 1:
Input: nums1 = [1,3,3,2], nums2 = [2,1,3,4], k = 3
Output: 12
Explanation:
The four possible subsequence scores are:
- We choose the indices 0, 1, and 2 with score = (1+3+3) * min(2,1,3) = 7.
- We choose the indices 0, 1, and 3 with score = (1+3+2) * min(2,1,4) = 6.
- We choose the indices 0, 2, and 3 with score = (1+3+2) * min(2,3,4) = 12.
- We choose the indices 1, 2, and 3 with score = (3+3+2) * min(1,3,4) = 8.
Therefore, we return the max score, which is 12.Example 2:
Input: nums1 = [4,2,3,1,1], nums2 = [7,5,10,9,6], k = 1
Output: 30
Explanation:
Choosing index 2 is optimal: nums1[2] * nums2[2] = 3 * 10 = 30 is the maximum possible score.
Constraints:
n == nums1.length == nums2.length1 <= n <= 1050 <= nums1[i], nums2[j] <= 1051 <= k <= n
Approaches
2 approaches with complexity analysis and trade-offs.
This approach iterates through every element in nums2 and considers it as the potential minimum for a valid subsequence. For each potential minimum nums2[i], it finds all other elements j where nums2[j] is greater than or equal to nums2[i]. From this group of candidates, it selects the k elements with the largest corresponding nums1 values to maximize the sum. The score is then calculated and compared with the maximum score found so far.
Algorithm
- Initialize
maxScore = 0. - For each index
ifrom0ton-1:- Let
minVal = nums2[i]. - Create a list
candidatesof allnums1[j]wherenums2[j] >= minVal. - If
candidates.size() < k, continue to the nexti. - Sort
candidatesin descending order. - Calculate
currentSumas the sum of the firstkelements ofcandidates. - Update
maxScore = max(maxScore, currentSum * minVal).
- Let
- Return
maxScore.
Walkthrough
The core idea is to fix the minimum element of the nums2 subsequence and then find the best nums1 sum. By iterating through every possible choice for this minimum value, we can explore all valid scenarios. For each choice, we gather all eligible elements and pick the best k of them to maximize the sum part of the score formula.
Here's the step-by-step algorithm:
- Initialize a variable
maxScoreto 0. - Iterate through each index
ifrom0ton-1. - For each
i, letminVal = nums2[i]. ThisminValis our candidate for the minimum of thekchosennums2values. - Create a list of
nums1values for all indicesjwherenums2[j] >= minVal. These are thenums1values we are allowed to choose from. - If the size of this list is less than
k, we cannot form a subsequence of lengthk, so we continue to the nexti. - If the list has
kor more elements, sort it in descending order. - Calculate the sum of the first
kelements from the sorted list. This gives the maximum possible sum ofnums1values for the chosenminVal. - Calculate the current score by multiplying this sum with
minVal. - Update
maxScore = max(maxScore, currentScore). - After iterating through all possible
i,maxScorewill hold the result.
import java.util.ArrayList;import java.util.Collections;import java.util.List; class Solution { public long maxScore(int[] nums1, int[] nums2, int k) { int n = nums1.length; long maxScore = 0; for (int i = 0; i < n; i++) { int currentMin = nums2[i]; List<Integer> candidates = new ArrayList<>(); for (int j = 0; j < n; j++) { if (nums2[j] >= currentMin) { candidates.add(nums1[j]); } } if (candidates.size() < k) { continue; } Collections.sort(candidates, Collections.reverseOrder()); long currentSum = 0; for (int l = 0; l < k; l++) { currentSum += candidates.get(l); } maxScore = Math.max(maxScore, currentSum * currentMin); } return maxScore; }}Complexity
Time
O(N^2 * logN). The outer loop runs `N` times. Inside, we iterate `N` times to build the `candidates` list (size up to `N`). Sorting this list takes `O(N log N)`. So, the total time is `N * (N + N log N) = O(N^2 log N)`.
Space
O(N). In each iteration of the outer loop, we create a `candidates` list that can store up to `N` elements.
Trade-offs
Pros
Conceptually simpler than the optimized approach.
Correctly breaks down the problem by fixing one variable (the minimum value).
Cons
Very inefficient due to repeated work. For each potential minimum, it rescans the entire array and re-sorts a potentially large list.
Will result in a "Time Limit Exceeded" (TLE) error for large inputs as specified in the constraints.
This is an optimized approach that avoids the repeated work of the previous method. The key idea is to process the elements in a specific order. We pair up nums1[i] and nums2[i] and sort these pairs based on nums2 values in descending order. By iterating through the sorted pairs, we can efficiently maintain the sum of the k largest nums1 values seen so far using a min-heap of size k.
Algorithm
- Create pairs
(nums1[i], nums2[i]). - Sort the pairs in descending order based on
nums2values. - Initialize a min-heap
pq,currentSum = 0,maxScore = 0. - For each pair
(n1, n2)in the sorted list:- Add
n1topqandcurrentSum. - If
pq.size() > k, remove the smallest element:currentSum -= pq.poll(). - If
pq.size() == k, calculate score:maxScore = max(maxScore, currentSum * n2).
- Add
- Return
maxScore.
Walkthrough
The score is (sum of k nums1 elements) * (min of k nums2 elements). If we fix the min of k nums2 elements to be m, we should choose k elements whose nums2 values are all at least m, and whose nums1 sum is maximized. This means we should pick the k largest nums1 values from the pool of eligible elements.
To do this efficiently, we can iterate through all possible values of m. The possible values for m are the elements of nums2. Let's process these m values from largest to smallest.
The algorithm is as follows:
- Create an array of pairs, where each pair contains
(nums1[i], nums2[i]). - Sort this array of pairs in descending order based on the
nums2values. This ensures that when we iterate through the pairs, thenums2value of the current pair is a candidate for the minimum, and all previously seen elements have anums2value greater than or equal to it. - Initialize a min-heap (PriorityQueue in Java) to keep track of the
klargestnums1values encountered so far. Also, initializecurrentSumto track the sum of elements in the heap andmaxScoreto 0. - Iterate through the sorted pairs
(n1, n2): a. Add the currentnums1value,n1, to the min-heap and tocurrentSum. b. If the heap's size exceedsk, it means we havek+1elements. To maintain theklargest, we must remove the smallest element. We poll from the min-heap (which removes the smallest element) and subtract it fromcurrentSum. c. Once the heap's size reachesk, we have a valid group ofkelements. The sum of theirnums1values iscurrentSum. The minimum of theirnums2values is the currentn2(due to our sorting). d. Calculate the scorecurrentSum * n2and updatemaxScoreif it's larger. - After the loop,
maxScoreholds the maximum possible score.
import java.util.Arrays;import java.util.PriorityQueue; class Solution { public long maxScore(int[] nums1, int[] nums2, int k) { int n = nums1.length; int[][] pairs = new int[n][2]; for (int i = 0; i < n; i++) { pairs[i][0] = nums1[i]; pairs[i][1] = nums2[i]; } // Sort pairs by nums2 in descending order Arrays.sort(pairs, (a, b) -> b[1] - a[1]); // Min-heap to store the k largest nums1 values PriorityQueue<Integer> minHeap = new PriorityQueue<>(k); long currentSum = 0; long maxScore = 0; for (int i = 0; i < n; i++) { int n1 = pairs[i][0]; int n2 = pairs[i][1]; minHeap.add(n1); currentSum += n1; if (minHeap.size() > k) { currentSum -= minHeap.poll(); } if (minHeap.size() == k) { maxScore = Math.max(maxScore, currentSum * n2); } } return maxScore; }}Complexity
Time
O(N log N). Sorting the pairs takes `O(N log N)`. The loop runs `N` times, and each heap operation (add/poll) takes `O(log K)`. So the loop takes `O(N log K)`. The total complexity is dominated by sorting, resulting in `O(N log N)`.
Space
O(N). We need `O(N)` space to store the pairs for sorting. The min-heap requires `O(K)` space. Thus, the total space complexity is `O(N + K) = O(N)`.
Trade-offs
Pros
Highly efficient and passes the time limits for the given constraints.
Clever use of sorting and a min-heap to avoid re-computation. By processing elements in order of decreasing
nums2values, we can maintain the sum of the topknums1values incrementally.
Cons
The logic is more complex to understand compared to the brute-force approach.
Requires extra space for storing pairs, which could be a concern for extremely large N if memory is severely constrained.
Solutions
Solution
class Solution {public long maxScore(int[] nums1, int[] nums2, int k) { int n = nums1.length; int[][] nums = new int[n][2]; for (int i = 0; i < n; ++i) { nums[i] = new int[]{nums1[i], nums2[i]}; } Arrays.sort(nums, (a, b)->b[1] - a[1]); long ans = 0, s = 0; PriorityQueue<Integer> q = new PriorityQueue<>(); for (int i = 0; i < n; ++i) { s += nums[i][0]; q.offer(nums[i][0]); if (q.size() == k) { ans = Math.max(ans, s * nums[i][1]); s -= q.poll(); } } return ans; }}class Solution {public: long long maxScore(vector<int> &nums1, vector<int> &nums2, int k) { int n = nums1.size(); vector<pair<int, int>> nums(n); for (int i = 0; i < n; ++i) { nums[i] = {-nums2[i], nums1[i]}; } sort(nums.begin(), nums.end()); priority_queue<int, vector<int>, greater<int>> q; long long ans = 0, s = 0; for (auto &[a, b] : nums) { s += b; q.push(b); if (q.size() == k) { ans = max(ans, s * -a); s -= q.top(); q.pop(); } } return ans; }};class Solution: def maxScore(self, nums1: List[int], nums2: List[int], k: int) -> int: nums = sorted(zip(nums2, nums1), reverse=True) q = [] ans = s = 0 for a, b in nums: s += b heappush(q, b) if len(q) == k: ans = max(ans, s * a) s -= heappop(q) return ansVideo walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.