3002. Maximum Size of a Set After Removals
Problem Description
You have two arrays nums1
and nums2
, both containing integers and having the same even length n
. Your task is to:
- Remove exactly
n/2
elements fromnums1
- Remove exactly
n/2
elements fromnums2
- Take all remaining elements from both arrays and put them into a set
s
(which automatically removes duplicates) - Find the maximum possible size of this set
The goal is to strategically choose which elements to remove from each array so that when you combine the remaining elements into a set, you get as many unique elements as possible.
For example, if you have:
nums1 = [1, 2, 3, 4]
andnums2 = [3, 4, 5, 6]
- You need to remove 2 elements from each array
- If you keep
[1, 2]
fromnums1
and[5, 6]
fromnums2
- The resulting set would be
{1, 2, 5, 6}
with size 4
The challenge is finding the optimal removal strategy to maximize the number of unique elements in the final set.
Intuition
To maximize the number of unique elements in the final set, we need to think about what types of elements exist across both arrays:
- Elements that appear only in
nums1
(unique tonums1
) - Elements that appear only in
nums2
(unique tonums2
) - Elements that appear in both arrays (common elements)
The key insight is that we want to keep as many different unique elements as possible. Since we must keep exactly n/2
elements from each array, our strategy should be:
- From
nums1
, prioritize keeping elements that are unique tonums1
(not innums2
), because these elements won't be available fromnums2
- From
nums2
, prioritize keeping elements that are unique tonums2
(not innums1
), because these elements won't be available fromnums1
- For common elements that appear in both arrays, we can get them from either array, so they serve as "flexible" choices
Let's denote:
s1 - s2
= elements unique tonums1
s2 - s1
= elements unique tonums2
s1 & s2
= common elements in both arrays
The maximum number of unique-to-nums1
elements we can keep is min(len(s1 - s2), n/2)
because we can only keep n/2
elements total from nums1
.
Similarly, the maximum number of unique-to-nums2
elements we can keep is min(len(s2 - s1), n/2)
.
After keeping these unique elements, any remaining slots from our n/2
quota in each array can be filled with common elements. Since common elements appear in both arrays, we can access all of them regardless of our choices.
The final answer is the sum of:
- Unique elements we keep from
nums1
- Unique elements we keep from
nums2
- All common elements (since we can always access them)
However, this sum is capped at n
(the total number of elements we keep from both arrays combined).
Learn more about Greedy patterns.
Solution Approach
The implementation follows the intuition by using set operations to categorize elements:
-
Convert arrays to sets: First, we create sets from both input arrays:
s1 = set(nums1) s2 = set(nums2)
This removes duplicates within each array and enables efficient set operations.
-
Calculate unique elements from each array:
len(s1 - s2)
gives the count of elements unique tonums1
len(s2 - s1)
gives the count of elements unique tonums2
Since we can only keep
n/2
elements from each array, we take the minimum:a = min(len(s1 - s2), n // 2) # max unique elements we can keep from nums1 b = min(len(s2 - s1), n // 2) # max unique elements we can keep from nums2
-
Calculate common elements:
len(s1 & s2)
gives the count of elements that appear in both arrays- These common elements are always accessible since we can pick them from either array when filling remaining slots
-
Compute the final result:
return min(a + b + len(s1 & s2), n)
The sum
a + b + len(s1 & s2)
represents:a
: unique elements kept fromnums1
b
: unique elements kept fromnums2
len(s1 & s2)
: all common elements (accessible from remaining slots)
We cap this at
n
because we're only keepingn
total elements (n/2
from each array).
The algorithm efficiently uses set operations with O(n) time complexity for set creation and O(1) space for the intermediate variables, making it optimal for this problem.
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example to illustrate the solution approach:
Input: nums1 = [1, 1, 2, 3, 4]
, nums2 = [2, 3, 5, 5, 6]
, n = 6
(arrays have length 6 each)
Step 1: Convert arrays to sets
s1 = {1, 2, 3, 4}
(removes duplicate 1 from nums1)s2 = {2, 3, 5, 6}
(removes duplicate 5 from nums2)
Step 2: Identify element categories
- Elements unique to nums1:
s1 - s2 = {1, 4}
(2 elements) - Elements unique to nums2:
s2 - s1 = {5, 6}
(2 elements) - Common elements:
s1 & s2 = {2, 3}
(2 elements)
Step 3: Calculate maximum unique elements we can keep
-
From nums1, we need to keep exactly
n/2 = 3
elements- We can keep at most
min(2, 3) = 2
unique elements from nums1 (elements 1 and 4) - This leaves 1 slot that must be filled with a common element
- We can keep at most
-
From nums2, we need to keep exactly
n/2 = 3
elements- We can keep at most
min(2, 3) = 2
unique elements from nums2 (elements 5 and 6) - This leaves 1 slot that must be filled with a common element
- We can keep at most
Step 4: Calculate the final result
- Unique from nums1: 2 elements ({1, 4})
- Unique from nums2: 2 elements ({5, 6})
- Common elements: 2 elements ({2, 3}) - we can access both since we have remaining slots
- Total:
min(2 + 2 + 2, 6) = 6
Optimal selection:
- Keep from nums1: [1, 4, 2] or [1, 4, 3] (2 unique + 1 common)
- Keep from nums2: [5, 6, 3] or [5, 6, 2] (2 unique + 1 common)
- Final set: {1, 2, 3, 4, 5, 6} with size = 6
The algorithm correctly identifies that by prioritizing unique elements from each array and using common elements to fill remaining slots, we can achieve the maximum possible set size of 6.
Solution Implementation
1class Solution:
2 def maximumSetSize(self, nums1: List[int], nums2: List[int]) -> int:
3 # Convert both lists to sets to get unique elements
4 set1 = set(nums1)
5 set2 = set(nums2)
6
7 # Get the original array length (both arrays have same length)
8 n = len(nums1)
9
10 # Calculate elements unique to set1 (not in set2)
11 # Limited by n/2 since we can only remove up to n/2 elements from nums1
12 unique_to_set1 = min(len(set1 - set2), n // 2)
13
14 # Calculate elements unique to set2 (not in set1)
15 # Limited by n/2 since we can only remove up to n/2 elements from nums2
16 unique_to_set2 = min(len(set2 - set1), n // 2)
17
18 # Calculate maximum possible set size:
19 # Sum of unique elements from each set plus common elements
20 # But total cannot exceed n (since we keep n/2 from each array)
21 common_elements = len(set1 & set2)
22 max_set_size = min(unique_to_set1 + unique_to_set2 + common_elements, n)
23
24 return max_set_size
25
1class Solution {
2 public int maximumSetSize(int[] nums1, int[] nums2) {
3 // Create sets to store unique elements from each array
4 Set<Integer> set1 = new HashSet<>();
5 Set<Integer> set2 = new HashSet<>();
6
7 // Add all elements from nums1 to set1
8 for (int num : nums1) {
9 set1.add(num);
10 }
11
12 // Add all elements from nums2 to set2
13 for (int num : nums2) {
14 set2.add(num);
15 }
16
17 // Get the length of the arrays (both arrays have the same length)
18 int n = nums1.length;
19
20 // Count elements unique to set1, unique to set2, and common to both
21 int uniqueToSet1 = 0; // Elements only in set1
22 int uniqueToSet2 = 0; // Elements only in set2
23 int commonElements = 0; // Elements in both sets
24
25 // Count elements that are only in set1 (not in set2)
26 for (int element : set1) {
27 if (!set2.contains(element)) {
28 uniqueToSet1++;
29 }
30 }
31
32 // Count elements in set2
33 for (int element : set2) {
34 if (!set1.contains(element)) {
35 // Elements only in set2
36 uniqueToSet2++;
37 } else {
38 // Elements common to both sets
39 commonElements++;
40 }
41 }
42
43 // We can remove at most n/2 elements from each array
44 // So limit the unique elements we can keep from each set
45 uniqueToSet1 = Math.min(uniqueToSet1, n / 2);
46 uniqueToSet2 = Math.min(uniqueToSet2, n / 2);
47
48 // The maximum set size is the sum of kept unique elements plus common elements
49 // But it cannot exceed n (the total number of elements we keep)
50 return Math.min(uniqueToSet1 + uniqueToSet2 + commonElements, n);
51 }
52}
53
1class Solution {
2public:
3 int maximumSetSize(vector<int>& nums1, vector<int>& nums2) {
4 // Convert input vectors to sets to get unique elements
5 unordered_set<int> uniqueSet1(nums1.begin(), nums1.end());
6 unordered_set<int> uniqueSet2(nums2.begin(), nums2.end());
7
8 // Get the original array size (both arrays have the same size)
9 int arraySize = nums1.size();
10
11 // Count elements that are unique to set1 (not in set2)
12 int uniqueToSet1Count = 0;
13 for (int element : uniqueSet1) {
14 if (uniqueSet2.count(element) == 0) {
15 ++uniqueToSet1Count;
16 }
17 }
18
19 // Count elements unique to set2 and common elements
20 int uniqueToSet2Count = 0;
21 int commonElementsCount = 0;
22 for (int element : uniqueSet2) {
23 if (uniqueSet1.count(element) == 0) {
24 ++uniqueToSet2Count;
25 } else {
26 ++commonElementsCount;
27 }
28 }
29
30 // We can take at most n/2 unique elements from each set
31 int maxFromSet1 = min(uniqueToSet1Count, arraySize / 2);
32 int maxFromSet2 = min(uniqueToSet2Count, arraySize / 2);
33
34 // The final set size is limited by the total array size
35 // We can take unique elements from both sets plus all common elements
36 return min(maxFromSet1 + maxFromSet2 + commonElementsCount, arraySize);
37 }
38};
39
1/**
2 * Calculates the maximum size of a set that can be formed by removing elements
3 * from two arrays while maintaining certain constraints.
4 *
5 * @param nums1 - First array of numbers
6 * @param nums2 - Second array of numbers
7 * @returns Maximum size of the resulting set
8 */
9function maximumSetSize(nums1: number[], nums2: number[]): number {
10 // Convert arrays to sets to get unique elements
11 const set1: Set<number> = new Set(nums1);
12 const set2: Set<number> = new Set(nums2);
13
14 // Store the original array length
15 const arrayLength: number = nums1.length;
16
17 // Initialize counters:
18 // uniqueToSet1: elements only in set1
19 // uniqueToSet2: elements only in set2
20 // commonElements: elements in both sets
21 let uniqueToSet1: number = 0;
22 let uniqueToSet2: number = 0;
23 let commonElements: number = 0;
24
25 // Count elements that are unique to set1
26 for (const element of set1) {
27 if (!set2.has(element)) {
28 uniqueToSet1++;
29 }
30 }
31
32 // Count elements that are unique to set2 and common elements
33 for (const element of set2) {
34 if (!set1.has(element)) {
35 uniqueToSet2++;
36 } else {
37 commonElements++;
38 }
39 }
40
41 // Limit unique elements from each set to half of the array length
42 uniqueToSet1 = Math.min(uniqueToSet1, arrayLength >> 1);
43 uniqueToSet2 = Math.min(uniqueToSet2, arrayLength >> 1);
44
45 // Return the minimum between the sum of all elements and the array length
46 return Math.min(uniqueToSet1 + uniqueToSet2 + commonElements, arrayLength);
47}
48
Time and Space Complexity
Time Complexity: O(n + m)
where n = len(nums1)
and m = len(nums2)
- Converting
nums1
to sets1
:O(n)
- Converting
nums2
to sets2
:O(m)
- Computing
s1 - s2
(set difference):O(len(s1))
which is at mostO(n)
- Computing
s2 - s1
(set difference):O(len(s2))
which is at mostO(m)
- Computing
s1 & s2
(set intersection):O(min(len(s1), len(s2)))
which is at mostO(min(n, m))
- The
min
andlen
operations areO(1)
for the final calculations
Overall time complexity is O(n + m)
, which simplifies to O(n)
since both arrays have the same length n
.
Space Complexity: O(n + m)
which simplifies to O(n)
- Creating set
s1
fromnums1
:O(n)
space - Creating set
s2
fromnums2
:O(m)
space - The set operations (
s1 - s2
,s2 - s1
,s1 & s2
) create new sets but their space is bounded by the original sets' sizes - Variables
a
,b
, andn
useO(1)
space
Since both input arrays have the same length n
, the space complexity is O(n + n) = O(n)
.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
Pitfall 1: Misunderstanding the Greedy Strategy for Common Elements
The Mistake: A common error is thinking that we should always try to maximize the unique elements from each array first, then "fill in" with common elements if we have space left. This leads to incorrect logic like:
# INCORRECT approach
unique_from_nums1 = len(set1 - set2)
unique_from_nums2 = len(set2 - set1)
common = len(set1 & set2)
# Wrong: trying to take all unique elements first
if unique_from_nums1 <= n//2 and unique_from_nums2 <= n//2:
result = unique_from_nums1 + unique_from_nums2 + min(common, n - unique_from_nums1 - unique_from_nums2)
Why It's Wrong: The issue is that after selecting unique elements from each array, you might not have enough "slots" left to accommodate all common elements optimally. The common elements are accessible from BOTH arrays, so they offer flexibility in selection.
The Correct Understanding: The solution correctly recognizes that:
- We can keep at most
n/2
elements from each array - Unique elements from nums1 can ONLY come from nums1
- Unique elements from nums2 can ONLY come from nums2
- Common elements can come from EITHER array
So the formula min(unique_to_set1 + unique_to_set2 + common_elements, n)
works because:
- If
unique_to_set1 + unique_to_set2 < n
, we have "spare slots" that can be filled with common elements - The common elements are always available since we can strategically choose which array to pick them from
Pitfall 2: Forgetting to Handle Duplicate Elements Within Each Array
The Mistake: Working directly with the original arrays without converting to sets first:
# INCORRECT - doesn't handle duplicates within arrays
n = len(nums1)
# This counts duplicates multiple times
unique_to_nums1 = sum(1 for x in nums1 if x not in nums2)
Why It's Wrong:
If nums1 = [1, 1, 2, 2]
and nums2 = [3, 3, 4, 4]
, the above code would count 4 unique elements in nums1, but there are actually only 2 unique values (1 and 2).
The Solution: Always convert to sets first to eliminate duplicates:
set1 = set(nums1) # Removes duplicates
set2 = set(nums2) # Removes duplicates
unique_to_set1 = len(set1 - set2) # Now counting unique VALUES, not occurrences
Pitfall 3: Incorrect Calculation of Available Slots
The Mistake:
Assuming we can keep more than n/2
elements from one array if we keep fewer from the other:
# INCORRECT logic
if len(set1 - set2) > n//2:
# Wrong: thinking we can keep more from nums1 if we keep less from nums2
extra_from_nums1 = len(set1 - set2) - n//2
available_from_nums2 = n//2 - extra_from_nums1
Why It's Wrong:
The problem explicitly states we must remove EXACTLY n/2
elements from each array, meaning we keep EXACTLY n/2
from each. This is a hard constraint, not flexible.
The Correct Approach:
Always cap the unique elements at n/2
for each array:
unique_to_set1 = min(len(set1 - set2), n // 2) # Never exceed n/2
unique_to_set2 = min(len(set2 - set1), n // 2) # Never exceed n/2
In a binary min heap, the minimum element can be found in:
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!