Facebook Pixel

3002. Maximum Size of a Set After Removals

MediumGreedyArrayHash Table
Leetcode Link

Problem Description

You have two arrays nums1 and nums2, both containing integers and having the same even length n. Your task is to:

  1. Remove exactly n/2 elements from nums1
  2. Remove exactly n/2 elements from nums2
  3. Take all remaining elements from both arrays and put them into a set s (which automatically removes duplicates)
  4. 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] and nums2 = [3, 4, 5, 6]
  • You need to remove 2 elements from each array
  • If you keep [1, 2] from nums1 and [5, 6] from nums2
  • 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.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

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:

  1. Elements that appear only in nums1 (unique to nums1)
  2. Elements that appear only in nums2 (unique to nums2)
  3. 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 to nums1 (not in nums2), because these elements won't be available from nums2
  • From nums2, prioritize keeping elements that are unique to nums2 (not in nums1), because these elements won't be available from nums1
  • 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 to nums1
  • s2 - s1 = elements unique to nums2
  • 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:

  1. 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.

  2. Calculate unique elements from each array:

    • len(s1 - s2) gives the count of elements unique to nums1
    • len(s2 - s1) gives the count of elements unique to nums2

    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
  3. 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
  4. Compute the final result:

    return min(a + b + len(s1 & s2), n)

    The sum a + b + len(s1 & s2) represents:

    • a: unique elements kept from nums1
    • b: unique elements kept from nums2
    • len(s1 & s2): all common elements (accessible from remaining slots)

    We cap this at n because we're only keeping n 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 Evaluator

Example 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
  • 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

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 set s1: O(n)
  • Converting nums2 to set s2: O(m)
  • Computing s1 - s2 (set difference): O(len(s1)) which is at most O(n)
  • Computing s2 - s1 (set difference): O(len(s2)) which is at most O(m)
  • Computing s1 & s2 (set intersection): O(min(len(s1), len(s2))) which is at most O(min(n, m))
  • The min and len operations are O(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 from nums1: O(n) space
  • Creating set s2 from nums2: 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, and n use O(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
Discover Your Strengths and Weaknesses: Take Our 3-Minute Quiz to Tailor Your Study Plan:

In a binary min heap, the minimum element can be found in:


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More