349. Intersection of Two Arrays
Problem Description
You are given two integer arrays nums1
and nums2
. Your task is to find the intersection of these two arrays - that is, find all elements that appear in both arrays.
The intersection should follow these rules:
- Each element in the result must be unique (no duplicates, even if an element appears multiple times in the original arrays)
- The elements can be returned in any order
For example:
- If
nums1 = [1, 2, 2, 1]
andnums2 = [2, 2]
, the intersection would be[2]
(only one 2, since we need unique elements) - If
nums1 = [4, 9, 5]
andnums2 = [9, 4, 9, 8, 4]
, the intersection would be[4, 9]
or[9, 4]
(order doesn't matter)
The solution uses Python's set operations to efficiently find the intersection. By converting both arrays to sets using set(nums1)
and set(nums2)
, duplicate elements are automatically removed. The &
operator performs set intersection, giving us all elements that exist in both sets. Finally, list()
converts the resulting set back to a list format for the return value.
Intuition
When we need to find common elements between two arrays, the natural thought is to check each element in one array against all elements in the other array. However, since we need unique elements in our result, we immediately think about using a data structure that handles uniqueness automatically - a set.
The key insight is recognizing that finding the intersection of two arrays is fundamentally the same as finding the intersection of two sets. Sets have two properties that make them perfect for this problem:
-
Automatic deduplication: When we convert an array to a set, duplicate elements are automatically removed. This solves our uniqueness requirement without any extra work.
-
Built-in intersection operation: Sets have a mathematical intersection operation that gives us exactly what we need - elements that exist in both sets.
Instead of manually tracking which elements we've seen (which would require additional space for bookkeeping and logic to avoid duplicates), we can leverage Python's set operations to do all the heavy lifting. The &
operator between two sets gives us their intersection in a single, efficient operation.
The approach essentially transforms the problem from "find unique common elements between two arrays" to "find the intersection of two sets" - a much simpler problem that has a direct, one-line solution. This is why set(nums1) & set(nums2)
elegantly solves the entire problem, and we just need to convert the result back to a list format to match the expected return type.
Solution Approach
The reference approach mentions using a hash table or array to track elements from nums1
, then iterating through nums2
to find common elements. Let's walk through both the reference approach and the provided solution:
Method 1: Hash Table/Array Approach (Reference)
-
Create a hash table or boolean array
s
to record which elements exist innums1
- If using an array, initialize an array of size 1001 (assuming element values are bounded)
- If using a hash table, create an empty set or dictionary
-
First pass - populate the tracking structure:
- Iterate through each element in
nums1
- Mark each element as present in
s
- Iterate through each element in
-
Second pass - find intersection:
- Initialize an empty result list
- Iterate through each element
x
innums2
- If
x
exists ins
:- Add
x
to the result - Remove
x
froms
(this ensures uniqueness - we only add each element once)
- Add
-
Return the result array
Method 2: Set Operations (Provided Solution)
The provided solution uses a more concise approach with Python's built-in set operations:
return list(set(nums1) & set(nums2))
This works in three steps:
set(nums1)
- Convert the first array to a set, removing all duplicatesset(nums2)
- Convert the second array to a set, removing all duplicates&
- Perform set intersection to get elements present in both setslist()
- Convert the resulting set back to a list
Both approaches have similar time complexity of O(n + m)
where n
and m
are the lengths of the two arrays. The set operation approach is more concise and leverages Python's optimized built-in operations, while the hash table approach gives more control over the process and can be easily adapted to other languages that might not have built-in set intersection operations.
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 understand how the solution works.
Given: nums1 = [4, 9, 5]
and nums2 = [9, 4, 9, 8, 4]
Step 1: Convert nums1 to a set
set(nums1)
converts[4, 9, 5]
to{4, 9, 5}
- No duplicates were removed since all elements were unique
Step 2: Convert nums2 to a set
set(nums2)
converts[9, 4, 9, 8, 4]
to{9, 4, 8}
- Notice how the duplicate 9's and 4's are automatically removed, leaving us with only unique elements
Step 3: Find the intersection using the & operator
{4, 9, 5} & {9, 4, 8}
- The & operator checks which elements exist in both sets:
- 4 exists in both sets ✓
- 9 exists in both sets ✓
- 5 only exists in the first set ✗
- 8 only exists in the second set ✗
- Result:
{4, 9}
Step 4: Convert back to a list
list({4, 9})
produces[4, 9]
or[9, 4]
(order may vary since sets are unordered)
Final Result: [4, 9]
This approach elegantly handles all the requirements:
- Uniqueness: Converting to sets automatically removes duplicates from both arrays
- Intersection: The & operator finds exactly the elements that appear in both sets
- Any order: Since sets are unordered, the result naturally can be in any order
The entire operation list(set(nums1) & set(nums2))
completes in a single line, making it both readable and efficient.
Solution Implementation
1class Solution:
2 def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
3 """
4 Find the intersection of two arrays.
5
6 Args:
7 nums1: First integer array
8 nums2: Second integer array
9
10 Returns:
11 List containing unique elements that appear in both arrays
12 """
13 # Convert both lists to sets to remove duplicates and enable set operations
14 set1 = set(nums1)
15 set2 = set(nums2)
16
17 # Use set intersection operator (&) to find common elements
18 # Convert the resulting set back to a list
19 return list(set1 & set2)
20
1class Solution {
2 /**
3 * Finds the intersection of two arrays, returning unique elements that appear in both arrays.
4 *
5 * @param nums1 First input array
6 * @param nums2 Second input array
7 * @return Array containing unique elements present in both input arrays
8 */
9 public int[] intersection(int[] nums1, int[] nums2) {
10 // Boolean array to track presence of elements from nums1
11 // Index represents the number value (constraint: 0 <= nums[i] <= 1000)
12 boolean[] seen = new boolean[1001];
13
14 // Mark all elements from nums1 as seen
15 for (int num : nums1) {
16 seen[num] = true;
17 }
18
19 // List to store intersection results
20 List<Integer> intersectionList = new ArrayList<>();
21
22 // Check each element in nums2
23 for (int num : nums2) {
24 // If element exists in nums1 and hasn't been added to result yet
25 if (seen[num]) {
26 intersectionList.add(num);
27 // Mark as false to avoid duplicates in the result
28 seen[num] = false;
29 }
30 }
31
32 // Convert List<Integer> to int[] array
33 return intersectionList.stream()
34 .mapToInt(Integer::intValue)
35 .toArray();
36 }
37}
38
1class Solution {
2public:
3 vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
4 // Boolean array to track presence of elements from nums1
5 // Index represents the number value (0-1000 based on problem constraints)
6 bool seen[1001];
7
8 // Initialize all elements to false
9 memset(seen, false, sizeof(seen));
10
11 // Mark all elements from nums1 as seen
12 for (int num : nums1) {
13 seen[num] = true;
14 }
15
16 // Result vector to store intersection elements
17 vector<int> result;
18
19 // Check each element in nums2
20 for (int num : nums2) {
21 // If element exists in nums1 and hasn't been added to result yet
22 if (seen[num]) {
23 result.push_back(num);
24 // Mark as false to avoid duplicates in result
25 seen[num] = false;
26 }
27 }
28
29 return result;
30 }
31};
32
1/**
2 * Finds the intersection of two arrays, returning unique elements that appear in both arrays
3 * @param nums1 - First array of numbers
4 * @param nums2 - Second array of numbers
5 * @returns Array containing unique elements present in both input arrays
6 */
7function intersection(nums1: number[], nums2: number[]): number[] {
8 // Create a set from the first array for O(1) lookup time
9 const nums1Set: Set<number> = new Set(nums1);
10
11 // Filter elements from nums2 that exist in nums1Set
12 const commonElements: number[] = nums2.filter((num: number) => nums1Set.has(num));
13
14 // Convert to Set to remove duplicates, then spread back to array
15 const uniqueIntersection: Set<number> = new Set(commonElements);
16
17 return [...uniqueIntersection];
18}
19
Time and Space Complexity
The time complexity is O(n + m)
, where n
is the length of nums1
and m
is the length of nums2
. This is because:
- Converting
nums1
to a set takesO(n)
time - Converting
nums2
to a set takesO(m)
time - The set intersection operation
&
takesO(min(n, m))
time - Converting the result set to a list takes
O(k)
time wherek
is the size of the intersection - Overall:
O(n) + O(m) + O(min(n, m)) + O(k) = O(n + m)
The space complexity is O(n + m)
in the worst case. This is because:
- Creating a set from
nums1
requiresO(n)
space - Creating a set from
nums2
requiresO(m)
space - The intersection result requires
O(min(n, m))
space - Overall:
O(n) + O(m) + O(min(n, m)) = O(n + m)
Note: The reference answer states space complexity as O(n)
, which could be interpreted as considering only the additional space for one set if we assume nums2
's set is created temporarily and discarded, or if n >= m
is assumed. However, the actual implementation creates sets for both arrays simultaneously, leading to O(n + m)
space complexity.
Common Pitfalls
1. Attempting to Preserve Element Frequency
A common mistake is thinking that the intersection should preserve how many times an element appears. For instance, if nums1 = [1, 2, 2, 1]
and nums2 = [2, 2]
, someone might expect [2, 2]
as the result instead of [2]
.
Why this happens: Confusion with the related problem "Intersection of Two Arrays II" which does preserve element frequencies.
Solution: Remember that this problem specifically asks for unique elements. Using sets automatically handles this requirement.
2. Memory Overhead with Large Arrays
When working with very large arrays, creating multiple set copies can consume significant memory, especially if the arrays contain many unique elements.
Alternative approach to reduce memory:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
# Use the smaller array as the base set to minimize memory
if len(nums1) > len(nums2):
nums1, nums2 = nums2, nums1
seen = set(nums1)
return list(seen.intersection(nums2))
3. Assuming Sorted Output
The problem states elements can be returned in any order, but developers sometimes assume the output should be sorted, leading to unnecessary sorting operations.
Why this matters: Adding sorted()
increases time complexity from O(n + m) to O((n + m) log(n + m)).
4. Type Confusion with Set Operations
Using the wrong set operation or forgetting to convert back to list:
# Wrong: Returns a set instead of list
return set(nums1) & set(nums2)
# Wrong: Uses union (|) instead of intersection (&)
return list(set(nums1) | set(nums2))
Solution: Always verify you're using the intersection operator (&
) and converting the final result to a list with list()
.
How many times is a tree node visited in a depth first search?
Recommended Readings
Tech Interview Pattern Two Pointers Introduction If you prefer videos here's a super quick introduction to Two Pointers div class responsive iframe iframe src https www youtube com embed xZ4AfXHQ1VQ title YouTube video player frameborder 0 allow accelerometer autoplay clipboard write encrypted media gyroscope picture in picture allowfullscreen iframe div Two pointers is a common interview
Binary Search Speedrun For each of the Speedrun questions you will be given a binary search related problem and a corresponding multiple choice question The multiple choice questions are related to the techniques and template s introduced in the binary search section It's recommended that you have gone through at
Sorting Summary Comparisons We presented quite a few sorting algorithms and it is essential to know the advantages and disadvantages of each one The basic algorithms are easy to visualize and easy to learn for beginner programmers because of their simplicity As such they will suffice if you don't know any advanced
Want a Structured Path to Master System Design Too? Don’t Miss This!