Maximum Sum of Almost Unique Subarray
MedPrompt
You are given an integer array nums and two positive integers m and k.
Return the maximum sum out of all almost unique subarrays of length k of nums. If no such subarray exists, return 0.
A subarray of nums is almost unique if it contains at least m distinct elements.
A subarray is a contiguous non-empty sequence of elements within an array.
Example 1:
k = 4Example 2:
Input: nums = [5,9,9,2,4,5,4], m = 1, k = 3
Output: 23
Explanation: There are 5 almost unique subarrays of size k. These subarrays are [5, 9, 9], [9, 9, 2], [9, 2, 4], [2, 4, 5], and [4, 5, 4]. Among these subarrays, the one with the maximum sum is [5, 9, 9] which has a sum of 23.Example 3:
k = 3
Constraints:
1 <= nums.length <= 2 * 1041 <= m <= k <= nums.length1 <= nums[i] <= 109
Approaches
2 approaches with complexity analysis and trade-offs.
This approach involves iterating through all possible subarrays of length k. For each subarray, we check if it meets the 'almost unique' criteria (at least m distinct elements) and, if so, calculate its sum. We keep track of the maximum sum found across all valid subarrays.
Algorithm
- Initialize
maxSumto 0. - Iterate through the array
numsfrom indexi = 0ton - k. - For each
i, create a newHashSetand initializecurrentSumto 0. - Create a subarray of length
kstarting ati. - Iterate through this subarray (from
j = itoi + k - 1): a. Addnums[j]to theHashSet. b. Addnums[j]tocurrentSum. - After iterating through the subarray, check if the size of the
HashSetis greater than or equal tom. - If it is, update
maxSum = Math.max(maxSum, currentSum). - After the outer loop finishes, return
maxSum.
Walkthrough
The brute-force method systematically examines every contiguous subarray of the specified length k.
- We use a loop that starts from the first element and ends at the last possible starting position for a subarray of length
k(nums.length - k). - Inside this loop, for each starting position
i, we form a subarraynums[i...i+k-1]. - To determine if this subarray is 'almost unique', we use a
HashSet. We populate the set with the elements of the current subarray. The size of theHashSetgives us the count of distinct elements. - If the count of distinct elements is
mor more, we proceed to calculate the sum of the elements in this subarray. - This sum is then compared with a running maximum, which is updated if the current sum is greater.
- After checking all possible subarrays, the final maximum sum is returned. If no 'almost unique' subarray is found, the initial maximum sum of 0 is returned.
import java.util.HashSet;import java.util.Set; class Solution { public long maximumSubarraySum(int[] nums, int m, int k) { long maxSum = 0; int n = nums.length; if (k > n) { return 0; } for (int i = 0; i <= n - k; i++) { Set<Integer> distinctElements = new HashSet<>(); long currentSum = 0; // Consider subarray nums[i...i+k-1] for (int j = i; j < i + k; j++) { distinctElements.add(nums[j]); currentSum += nums[j]; } // Check if the subarray is almost unique if (distinctElements.size() >= m) { maxSum = Math.max(maxSum, currentSum); } } return maxSum; }}Complexity
Time
O(n * k), where `n` is the length of `nums`. The outer loop runs `n-k+1` times, and for each iteration, we loop `k` times to build the set and calculate the sum. This results in a quadratic time complexity in the worst case (when `k` is proportional to `n`).
Space
O(k), as we use a `HashSet` to store up to `k` elements for each subarray.
Trade-offs
Pros
Simple to conceptualize and implement.
Correct for all cases, though not efficient.
Cons
Highly inefficient due to redundant calculations.
The time complexity of O(n*k) will lead to a 'Time Limit Exceeded' (TLE) error on larger test cases.
Solutions
Solution
public class Solution { public long MaxSum(IList < int > nums, int m, int k) { Dictionary < int, int > cnt = new Dictionary < int, int > (); int n = nums.Count; long s = 0; for (int i = 0; i < k; ++i) { if (!cnt.ContainsKey(nums[i])) { cnt[nums[i]] = 1; } else { cnt[nums[i]]++; } s += nums[i]; } long ans = cnt.Count >= m ? s : 0; for (int i = k; i < n; ++i) { if (!cnt.ContainsKey(nums[i])) { cnt[nums[i]] = 1; } else { cnt[nums[i]]++; } if (cnt.ContainsKey(nums[i - k])) { cnt[nums[i - k]]--; if (cnt[nums[i - k]] == 0) { cnt.Remove(nums[i - k]); } } s += nums[i] - nums[i - k]; if (cnt.Count >= m) { ans = Math.Max(ans, s); } } return ans; }}Video 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.