3487. Maximum Unique Subarray Sum After Deletion
Problem Description
You are given an integer array nums
. You can delete any number of elements from the array (but cannot delete all elements - the array must remain non-empty). After deleting elements, you need to select a contiguous subarray from the remaining elements.
The selected subarray must satisfy two conditions:
- All elements in the subarray must be unique (no duplicates)
- The sum of elements in the subarray should be as large as possible
Your task is to return the maximum possible sum of such a subarray.
For example, if you have nums = [1, 2, 3, 2, 4]
, you could:
- Delete nothing and select subarray
[1, 2, 3]
with sum = 6 - Delete nothing and select subarray
[3, 2, 4]
with sum = 9 - Delete the second occurrence of 2 to get
[1, 2, 3, 4]
and select the entire array with sum = 10
The key insight is that you want to maximize the sum while ensuring all elements in your chosen subarray are unique. Since you can delete elements strategically, you can remove duplicates and negative numbers that would decrease your sum, then select the optimal subarray from what remains.
Intuition
Let's think about what we're trying to maximize. We want a subarray with unique elements that has the maximum sum possible.
First observation: Since we can delete any elements we want (except all of them), we have complete control over which elements remain in the array. This is a powerful ability - we can essentially "design" our array to be optimal.
Second observation: For maximizing sum with unique elements, negative numbers are generally bad for us (they decrease the sum), and duplicate positive numbers are also problematic (we can only use one copy due to the uniqueness constraint).
This leads to a key insight: Why would we ever keep negative numbers or duplicates if we can delete them? If we have the freedom to delete elements, the optimal strategy becomes clear:
- Keep all unique positive numbers
- Delete all negative numbers (unless all numbers are negative)
- Delete duplicate occurrences of positive numbers
Wait, but the problem asks for a subarray, not just any subset. Here's the crucial realization: After we delete all unwanted elements (negatives and duplicates), we can arrange the remaining elements however we want. Since all remaining elements are positive and unique, we'd want them all in one contiguous subarray to maximize the sum.
Special case: If all numbers in the original array are negative or zero, we can't delete everything (array must be non-empty). In this case, the best we can do is select a subarray containing just the maximum element (which would be the least negative or zero).
This greedy approach works because we're not constrained by the original order - we can delete and rearrange to create the optimal configuration where all unique positive numbers form a single contiguous subarray.
Learn more about Greedy patterns.
Solution Approach
The implementation follows the greedy strategy we identified:
-
Find the maximum element: First, we find the maximum value
mx
in the array usingmx = max(nums)
. This helps us handle the special case where all elements are non-positive. -
Handle the special case: If
mx <= 0
, it means all elements in the array are negative or zero. Since we must keep at least one element and form a non-empty subarray, the best we can do is returnmx
(the least negative or zero value). -
Collect unique positive numbers: If there are positive numbers in the array, we use a hash set
s
to track which positive numbers we've already seen. We iterate through the array and for each elementx
:- Skip if
x < 0
(negative numbers decrease our sum) - Skip if
x in s
(we've already counted this positive number) - Otherwise, add
x
to our running sumans
and mark it as seen by adding to sets
- Skip if
The algorithm works as follows:
class Solution:
def maxSum(self, nums: List[int]) -> int:
mx = max(nums)
if mx <= 0:
return mx
ans = 0
s = set()
for x in nums:
if x < 0 or x in s:
continue
ans += x
s.add(x)
return ans
Time Complexity: O(n)
where n
is the length of the array. We make one pass to find the maximum and one pass to collect unique positive numbers.
Space Complexity: O(k)
where k
is the number of unique positive integers in the array. In the worst case, this could be O(n)
if all elements are unique and positive.
The beauty of this solution is that it transforms the problem from finding an optimal subarray to simply collecting all unique positive numbers, leveraging the fact that we can delete elements to create the ideal configuration.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with nums = [3, -1, 2, 3, 5, -2, 2]
.
Step 1: Find the maximum element
mx = max(nums) = 5
- Since
mx > 0
, we have positive numbers, so we proceed to collect unique positives.
Step 2: Initialize tracking variables
ans = 0
(running sum)s = set()
(to track seen positive numbers)
Step 3: Iterate through the array
Element | Action | Reason | ans | s |
---|---|---|---|---|
3 | Add to sum | Positive, not seen | 3 | {3} |
-1 | Skip | Negative | 3 | {3} |
2 | Add to sum | Positive, not seen | 5 | {3, 2} |
3 | Skip | Already in set | 5 | {3, 2} |
5 | Add to sum | Positive, not seen | 10 | {3, 2, 5} |
-2 | Skip | Negative | 10 | {3, 2, 5} |
2 | Skip | Already in set | 10 | {3, 2, 5} |
Step 4: Return result
- Return
ans = 10
This corresponds to deleting -1
, -2
, and the duplicate occurrences of 3
and 2
, leaving us with [3, 2, 5]
. We can then select this entire array as our subarray, giving us the maximum sum of 10.
Special case example: If nums = [-4, -2, -5]
, then mx = -2
. Since mx <= 0
, we immediately return -2
, which represents selecting just the subarray [-2]
(the least negative value).
Solution Implementation
1from typing import List
2
3class Solution:
4 def maxSum(self, nums: List[int]) -> int:
5 # Find the maximum value in the array
6 max_value = max(nums)
7
8 # If all numbers are non-positive, return the maximum value
9 if max_value <= 0:
10 return max_value
11
12 # Initialize the sum of unique positive numbers
13 total_sum = 0
14
15 # Set to track which positive numbers we've already added
16 seen_numbers = set()
17
18 # Iterate through each number in the array
19 for num in nums:
20 # Skip negative numbers and duplicates
21 if num < 0 or num in seen_numbers:
22 continue
23
24 # Add unique positive number to the sum
25 total_sum += num
26
27 # Mark this number as seen
28 seen_numbers.add(num)
29
30 return total_sum
31
1class Solution {
2 public int maxSum(int[] nums) {
3 // Find the maximum element in the array
4 int maxElement = Arrays.stream(nums).max().getAsInt();
5
6 // If the maximum element is non-positive, return it
7 // (handles case where all elements are negative or zero)
8 if (maxElement <= 0) {
9 return maxElement;
10 }
11
12 // Boolean array to track which positive numbers we've already included
13 // Size 201 to handle numbers from 0 to 200
14 boolean[] isIncluded = new boolean[201];
15
16 // Initialize sum of unique positive elements
17 int sum = 0;
18
19 // Iterate through all numbers in the array
20 for (int num : nums) {
21 // Skip negative numbers or numbers we've already included
22 if (num < 0 || isIncluded[num]) {
23 continue;
24 }
25
26 // Add unique positive number to sum
27 sum += num;
28
29 // Mark this number as included to avoid duplicates
30 isIncluded[num] = true;
31 }
32
33 return sum;
34 }
35}
36
1class Solution {
2public:
3 int maxSum(vector<int>& nums) {
4 // Find the maximum element in the array
5 int maxElement = ranges::max(nums);
6
7 // If all elements are non-positive, return the maximum element
8 if (maxElement <= 0) {
9 return maxElement;
10 }
11
12 // Set to track unique positive numbers we've already added
13 unordered_set<int> seen;
14
15 // Variable to store the sum of unique positive numbers
16 int result = 0;
17
18 // Iterate through each number in the array
19 for (int num : nums) {
20 // Skip negative numbers and duplicates
21 if (num < 0 || seen.contains(num)) {
22 continue;
23 }
24
25 // Add unique positive number to the sum
26 result += num;
27
28 // Mark this number as seen
29 seen.insert(num);
30 }
31
32 return result;
33 }
34};
35
1/**
2 * Finds the maximum sum of unique positive numbers from the array.
3 * If all numbers are non-positive, returns the maximum value.
4 * @param nums - Array of numbers to process
5 * @returns Maximum sum of unique positive numbers, or max value if all non-positive
6 */
7function maxSum(nums: number[]): number {
8 // Find the maximum value in the array
9 const maxValue: number = Math.max(...nums);
10
11 // If the maximum value is non-positive, return it
12 // (This handles the case where all numbers are negative or zero)
13 if (maxValue <= 0) {
14 return maxValue;
15 }
16
17 // Set to track unique numbers we've already added
18 const visitedNumbers: Set<number> = new Set<number>();
19
20 // Initialize the sum of unique positive numbers
21 let totalSum: number = 0;
22
23 // Iterate through each number in the array
24 for (const currentNumber of nums) {
25 // Skip negative numbers or numbers we've already seen
26 if (currentNumber < 0 || visitedNumbers.has(currentNumber)) {
27 continue;
28 }
29
30 // Add the unique positive number to our sum
31 totalSum += currentNumber;
32
33 // Mark this number as visited
34 visitedNumbers.add(currentNumber);
35 }
36
37 return totalSum;
38}
39
Time and Space Complexity
The time complexity is O(n)
, where n
is the length of the array nums
. This is because:
- Finding the maximum element using
max(nums)
takesO(n)
time - The for loop iterates through all elements in
nums
once, which takesO(n)
time - The set operations
x in s
ands.add(x)
areO(1)
on average - Overall, the dominant operations are linear scans through the array
The space complexity is O(n)
, where n
is the length of the array nums
. This is because:
- The set
s
can potentially store all unique positive elements fromnums
- In the worst case where all elements are unique and positive, the set will contain
n
elements - Therefore, the space required grows linearly with the input size
Learn more about how to find time and space complexity quickly.
Common Pitfalls
Pitfall 1: Misunderstanding the Problem Requirements
The Mistake: Many people initially interpret this problem as a traditional "maximum subarray sum with unique elements" problem where you must find a contiguous subarray in the original array without any deletions allowed. They might try to use sliding window or dynamic programming approaches to find the best contiguous subarray with unique elements.
Why It Happens: The problem statement mentions "contiguous subarray" which triggers pattern recognition for classic subarray problems. Readers might miss the crucial detail that you can delete elements first, which fundamentally changes the problem.
The Fix: Recognize that the ability to delete elements means you can rearrange the array to your advantage. Once you can delete any elements you want (except all of them), you can remove all duplicates and negative numbers, then arrange the remaining unique positive numbers contiguously. This transforms the problem into simply summing all unique positive values.
Pitfall 2: Forgetting Edge Cases with Non-Positive Numbers
The Mistake: Implementing only the logic to sum unique positive numbers without handling the case where all numbers in the array are negative or zero:
def maxSum(self, nums: List[int]) -> int:
total_sum = 0
seen = set()
for num in nums:
if num > 0 and num not in seen:
total_sum += num
seen.add(num)
return total_sum # Returns 0 when all numbers are negative!
Why It Happens: When focusing on maximizing the sum, it's natural to think "just take all positive unique numbers." However, the problem requires the array to remain non-empty, so when all numbers are non-positive, returning 0 violates this constraint.
The Fix: Always check if the maximum value in the array is non-positive. If it is, return that maximum value (the least negative number) since you must keep at least one element:
max_value = max(nums)
if max_value <= 0:
return max_value
Pitfall 3: Overthinking the Subarray Selection
The Mistake: After collecting unique positive numbers, trying to find the "optimal contiguous subarray" among them, perhaps using Kadane's algorithm or similar approaches.
Why It Happens: The phrase "contiguous subarray" in the problem statement makes it seem like you need to carefully select which portion of your processed array to use.
The Fix: Once you've deleted all unwanted elements (negatives and duplicates), you can arrange the remaining unique positive numbers however you want. The optimal strategy is always to include all of them in your subarray since they're all positive and contribute to the sum. The "contiguous" requirement becomes trivial when you control the arrangement.
How would you design a stack which has a function min
that returns the minimum element in the stack, in addition to push
and pop
? All push
, pop
, min
should have running time O(1)
.
Recommended Readings
Greedy Introduction div class responsive iframe iframe src https www youtube com embed WTslqPbj7I title YouTube video player frameborder 0 allow accelerometer autoplay clipboard write encrypted media gyroscope picture in picture web share allowfullscreen iframe div When do we use greedy Greedy algorithms tend to solve optimization problems Typically they will ask you to calculate the max min of some value Commonly you may see this phrased in the problem as max min longest shortest largest smallest etc These keywords can be identified by just scanning
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Donβt Miss This!