Facebook Pixel

2956. Find Common Elements Between Two Arrays

EasyArrayHash Table
Leetcode Link

Problem Description

You are given two integer arrays nums1 and nums2 with sizes n and m respectively.

Your task is to calculate two values:

  1. answer1: Count how many indices i in nums1 have the property that nums1[i] exists somewhere in nums2. In other words, for each element at position i in nums1, check if that element appears anywhere in nums2. Count all such positions.

  2. answer2: Count how many indices i in nums2 have the property that nums2[i] exists somewhere in nums1. In other words, for each element at position i in nums2, check if that element appears anywhere in nums1. Count all such positions.

Return these two counts as an array [answer1, answer2].

For example, if nums1 = [2, 3, 2] and nums2 = [1, 2]:

  • For answer1: We check each element in nums1
    • nums1[0] = 2 exists in nums2, so we count it
    • nums1[1] = 3 does not exist in nums2, so we don't count it
    • nums1[2] = 2 exists in nums2, so we count it
    • Therefore, answer1 = 2
  • For answer2: We check each element in nums2
    • nums2[0] = 1 does not exist in nums1, so we don't count it
    • nums2[1] = 2 exists in nums1, so we count it
    • Therefore, answer2 = 1
  • The result would be [2, 1]
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The key insight is that we need to efficiently check membership - whether an element from one array exists in another array. When we need to repeatedly check if elements exist in a collection, using a hash set is the natural choice because it provides O(1) lookup time.

Think about the naive approach first: for each element in nums1, we'd need to scan through all of nums2 to check if it exists there. This would take O(n * m) time. Similarly for checking elements from nums2 in nums1.

However, if we first convert both arrays into sets, we can transform this into a much more efficient solution. Sets automatically handle duplicates and give us constant-time membership checking.

Once we have s1 = set(nums1) and s2 = set(nums2), the problem becomes straightforward:

  • For each element x in the original nums1 array, check if x in s2 (constant time)
  • For each element x in the original nums2 array, check if x in s1 (constant time)

The beauty of this approach is that even though we iterate through the original arrays (not the sets), we're using the sets purely for fast membership testing. This preserves the count of duplicate elements in the original arrays while leveraging the speed of set operations.

The solution elegantly uses Python's generator expressions with sum() to count the matching elements in a single line for each array, making the code both efficient and concise.

Solution Approach

The implementation follows a straightforward approach using hash tables (sets) for efficient membership checking.

Step 1: Create Sets from Arrays

First, we convert both input arrays into sets:

s1, s2 = set(nums1), set(nums2)

This transformation allows us to perform O(1) membership checks. The sets s1 and s2 contain the unique elements from nums1 and nums2 respectively.

Step 2: Count Matching Elements

We need to count elements at each index of the original arrays that exist in the opposite set:

For answer1, we iterate through each element x in the original nums1 array and check if it exists in s2:

sum(x in s2 for x in nums1)

This generator expression checks each element and produces True (counted as 1) or False (counted as 0), then sums up all the 1s.

For answer2, we do the same but iterate through nums2 and check against s1:

sum(x in s1 for x in nums2)

Step 3: Return Results

Both counts are computed and returned as a list:

return [sum(x in s2 for x in nums1), sum(x in s1 for x in nums2)]

Time Complexity: O(n + m) where n and m are the lengths of nums1 and nums2. Creating the sets takes O(n + m) time, and checking membership for all elements also takes O(n + m) time.

Space Complexity: O(n + m) for storing the two sets containing unique elements from both arrays.

The solution efficiently handles duplicate elements in the original arrays - each occurrence is counted separately in the final answer, even though the sets only store unique values.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through the solution with a concrete example:

Given: nums1 = [4, 3, 2, 3, 1] and nums2 = [2, 2, 5, 2, 3, 6]

Step 1: Create Sets

  • Convert nums1 to set: s1 = {1, 2, 3, 4}
  • Convert nums2 to set: s2 = {2, 3, 5, 6}

Step 2: Calculate answer1 Count how many elements in nums1 exist in s2:

  • nums1[0] = 4: Is 4 in s2? No (4 not in {2, 3, 5, 6}) → count: 0
  • nums1[1] = 3: Is 3 in s2? Yes (3 is in {2, 3, 5, 6}) → count: 1
  • nums1[2] = 2: Is 2 in s2? Yes (2 is in {2, 3, 5, 6}) → count: 2
  • nums1[3] = 3: Is 3 in s2? Yes (3 is in {2, 3, 5, 6}) → count: 3
  • nums1[4] = 1: Is 1 in s2? No (1 not in {2, 3, 5, 6}) → count: 3

answer1 = 3

Step 3: Calculate answer2 Count how many elements in nums2 exist in s1:

  • nums2[0] = 2: Is 2 in s1? Yes (2 is in {1, 2, 3, 4}) → count: 1
  • nums2[1] = 2: Is 2 in s1? Yes (2 is in {1, 2, 3, 4}) → count: 2
  • nums2[2] = 5: Is 5 in s1? No (5 not in {1, 2, 3, 4}) → count: 2
  • nums2[3] = 2: Is 2 in s1? Yes (2 is in {1, 2, 3, 4}) → count: 3
  • nums2[4] = 3: Is 3 in s1? Yes (3 is in {1, 2, 3, 4}) → count: 4
  • nums2[5] = 6: Is 6 in s1? No (6 not in {1, 2, 3, 4}) → count: 4

answer2 = 4

Result: [3, 4]

Note how duplicate values (like the multiple 3s in nums1 and multiple 2s in nums2) are each counted individually when they exist in the opposite set, even though the sets themselves only store unique values.

Solution Implementation

1class Solution:
2    def findIntersectionValues(self, nums1: List[int], nums2: List[int]) -> List[int]:
3        # Convert both lists to sets for O(1) lookup time
4        set1 = set(nums1)
5        set2 = set(nums2)
6      
7        # Count elements in nums1 that exist in set2
8        count1 = sum(1 for num in nums1 if num in set2)
9      
10        # Count elements in nums2 that exist in set1
11        count2 = sum(1 for num in nums2 if num in set1)
12      
13        # Return both counts as a list
14        return [count1, count2]
15
1class Solution {
2    public int[] findIntersectionValues(int[] nums1, int[] nums2) {
3        // Create boolean arrays to mark presence of elements (0-100 range)
4        // Using size 101 to accommodate values from 0 to 100
5        int[] existsInNums1 = new int[101];
6        int[] existsInNums2 = new int[101];
7      
8        // Mark elements present in nums1
9        for (int num : nums1) {
10            existsInNums1[num] = 1;
11        }
12      
13        // Mark elements present in nums2
14        for (int num : nums2) {
15            existsInNums2[num] = 1;
16        }
17      
18        // Initialize result array
19        // result[0]: count of elements in nums1 that appear in nums2
20        // result[1]: count of elements in nums2 that appear in nums1
21        int[] result = new int[2];
22      
23        // Count elements from nums1 that exist in nums2
24        for (int num : nums1) {
25            result[0] += existsInNums2[num];
26        }
27      
28        // Count elements from nums2 that exist in nums1
29        for (int num : nums2) {
30            result[1] += existsInNums1[num];
31        }
32      
33        return result;
34    }
35}
36
1class Solution {
2public:
3    vector<int> findIntersectionValues(vector<int>& nums1, vector<int>& nums2) {
4        // Arrays to mark presence of elements (0-100 range based on constraints)
5        // exists_in_nums1[i] = 1 if i exists in nums1, 0 otherwise
6        int exists_in_nums1[101] = {};
7        int exists_in_nums2[101] = {};
8      
9        // Mark all elements present in nums1
10        for (int& num : nums1) {
11            exists_in_nums1[num] = 1;
12        }
13      
14        // Mark all elements present in nums2
15        for (int& num : nums2) {
16            exists_in_nums2[num] = 1;
17        }
18      
19        // Result vector: [count1, count2]
20        // count1: number of indices in nums1 where nums1[i] exists in nums2
21        // count2: number of indices in nums2 where nums2[i] exists in nums1
22        vector<int> result(2);
23      
24        // Count elements in nums1 that exist in nums2
25        for (int& num : nums1) {
26            result[0] += exists_in_nums2[num];
27        }
28      
29        // Count elements in nums2 that exist in nums1
30        for (int& num : nums2) {
31            result[1] += exists_in_nums1[num];
32        }
33      
34        return result;
35    }
36};
37
1/**
2 * Finds the count of elements in each array that exist in the other array
3 * @param nums1 - First array of numbers
4 * @param nums2 - Second array of numbers
5 * @returns Array with two values: [count of nums1 elements in nums2, count of nums2 elements in nums1]
6 */
7function findIntersectionValues(nums1: number[], nums2: number[]): number[] {
8    // Create frequency arrays to mark presence of elements (0-100 range)
9    // Using arrays as hash sets for O(1) lookup
10    const presenceInNums1: number[] = Array(101).fill(0);
11    const presenceInNums2: number[] = Array(101).fill(0);
12  
13    // Mark elements present in nums1
14    for (const num of nums1) {
15        presenceInNums1[num] = 1;
16    }
17  
18    // Mark elements present in nums2
19    for (const num of nums2) {
20        presenceInNums2[num] = 1;
21    }
22  
23    // Initialize result array with two counters
24    const result: number[] = Array(2).fill(0);
25  
26    // Count how many elements from nums1 exist in nums2
27    for (const num of nums1) {
28        result[0] += presenceInNums2[num];
29    }
30  
31    // Count how many elements from nums2 exist in nums1
32    for (const num of nums2) {
33        result[1] += presenceInNums1[num];
34    }
35  
36    return result;
37}
38

Time and Space Complexity

Time Complexity: O(n + m)

  • Creating set(nums1) takes O(n) time where n is the length of nums1
  • Creating set(nums2) takes O(m) time where m is the length of nums2
  • The first sum comprehension sum(x in s2 for x in nums1) iterates through all n elements in nums1, and each set membership check x in s2 takes O(1) average time, resulting in O(n) total time
  • The second sum comprehension sum(x in s1 for x in nums2) iterates through all m elements in nums2, and each set membership check x in s1 takes O(1) average time, resulting in O(m) total time
  • Overall time complexity: O(n) + O(m) + O(n) + O(m) = O(n + m)

Space Complexity: O(n + m)

  • Set s1 stores unique elements from nums1, which in the worst case contains all n elements, requiring O(n) space
  • Set s2 stores unique elements from nums2, which in the worst case contains all m elements, requiring O(m) space
  • The generator expressions in the sum functions use O(1) additional space
  • Overall space complexity: O(n) + O(m) = O(n + m)

Learn more about how to find time and space complexity quickly.

Common Pitfalls

Pitfall 1: Confusing Set Intersection with Index Counting

The Mistake: A common error is misunderstanding the problem and calculating the intersection of two sets instead of counting individual occurrences:

# WRONG approach
def findIntersectionValues(self, nums1: List[int], nums2: List[int]) -> List[int]:
    set1 = set(nums1)
    set2 = set(nums2)
  
    # This counts unique elements, not occurrences!
    intersection = set1 & set2
    return [len(intersection), len(intersection)]  # Incorrect!

Why It's Wrong: The problem asks for the count of indices where elements exist in the other array, not the count of unique common elements. If nums1 = [2, 3, 2] and nums2 = [1, 2], the intersection approach would incorrectly return [1, 1] instead of [2, 1].

The Fix: Count each occurrence separately by iterating through the original arrays:

# CORRECT approach
count1 = sum(1 for num in nums1 if num in set2)
count2 = sum(1 for num in nums2 if num in set1)

Pitfall 2: Creating Sets from Wrong Arrays

The Mistake: Creating sets from the same array you're iterating through:

# WRONG - checking if nums1 elements exist in nums1's set
count1 = sum(1 for num in nums1 if num in set1)  # Should be set2!
count2 = sum(1 for num in nums2 if num in set2)  # Should be set1!

Why It's Wrong: This would always count all elements since every element obviously exists in its own set, giving incorrect results like [len(nums1), len(nums2)].

The Fix: Ensure you're checking against the opposite array's set:

# Check nums1 elements against set2, and nums2 elements against set1
count1 = sum(1 for num in nums1 if num in set2)
count2 = sum(1 for num in nums2 if num in set1)

Pitfall 3: Not Handling Duplicates Correctly

The Mistake: Trying to optimize by removing duplicates from the original arrays before counting:

# WRONG - removing duplicates changes the count
unique_nums1 = list(set(nums1))
unique_nums2 = list(set(nums2))
count1 = sum(1 for num in unique_nums1 if num in set2)

Why It's Wrong: The problem specifically wants to count each index/occurrence. If nums1 = [2, 2, 2] and nums2 = [2], the answer should be [3, 1], not [1, 1].

The Fix: Iterate through the original arrays with all their duplicates intact, only use sets for membership checking:

# Keep original arrays for iteration, use sets only for lookup
set1 = set(nums1)
set2 = set(nums2)
count1 = sum(1 for num in nums1 if num in set2)  # nums1, not set1
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

Depth first search is equivalent to which of the tree traversal order?


Recommended Readings

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

Load More