Facebook Pixel

2032. Two Out of Three

EasyBit ManipulationArrayHash Table
Leetcode Link

Problem Description

You are given three integer arrays: nums1, nums2, and nums3. Your task is to find all the values that appear in at least two out of these three arrays. The result should contain only distinct values (no duplicates), and you can return them in any order.

For example, if a number appears in nums1 and nums2, it should be included in the result. Similarly, if a number appears in all three arrays, it should also be included (since it appears in at least two arrays). However, if a number appears only in one array, it should not be included.

The solution approach converts each array into a set to remove duplicates within each array. Then it checks every possible integer from 1 to 100 to see if it appears in at least two of the three sets. The expression (i in s1) + (i in s2) + (i in s3) counts how many sets contain the number i (since True equals 1 and False equals 0 in Python). If this sum is greater than 1, it means the number appears in at least two arrays and should be included in the result.

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 track which numbers appear in multiple arrays, not how many times they appear within a single array. This immediately suggests using sets to eliminate duplicates within each array - if a number appears multiple times in nums1, we only care that it exists in nums1, not how many times.

Once we have sets, we need to find the intersection of at least two sets. Instead of computing pairwise intersections like (s1 ∩ s2) ∪ (s1 ∩ s3) ∪ (s2 ∩ s3), which would be complex, we can think about this problem differently: for each possible number, count how many sets contain it.

Since the problem constraints typically limit the range of values (here, numbers are between 1 and 100), we can simply check each possible value. For each number i, we check its presence in all three sets. The clever part is using boolean arithmetic: (i in s1) + (i in s2) + (i in s3) gives us a count of how many sets contain i. If this count is 2 or 3, then i appears in at least two arrays and should be included in our answer.

This approach transforms the problem from "find overlapping elements" to "count occurrences across sets," which is conceptually simpler and leads to clean, readable code.

Solution Approach

The implementation follows a straightforward approach using sets and enumeration:

  1. Convert arrays to sets: First, we convert each input array into a set:

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

    This removes any duplicate values within each array, since we only care about whether a value exists in an array, not how many times it appears.

  2. Enumerate possible values: Since the problem constraints indicate that values range from 1 to 100, we iterate through this range:

    for i in range(1, 101)
  3. Count occurrences across sets: For each number i, we check its presence in all three sets using the expression:

    (i in s1) + (i in s2) + (i in s3)

    This leverages Python's boolean arithmetic where True equals 1 and False equals 0. The result is a count of how many sets contain the number i.

  4. Filter based on count: We include i in our result only if it appears in at least two sets:

    if (i in s1) + (i in s2) + (i in s3) > 1
  5. List comprehension: The entire logic is elegantly combined into a single list comprehension:

    return [i for i in range(1, 101) if (i in s1) + (i in s2) + (i in s3) > 1]

The time complexity is O(n1 + n2 + n3) for creating the sets, plus O(100) for the enumeration, which simplifies to O(n) where n is the total number of elements. The space complexity is O(n) for storing the sets.

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 small example to illustrate the solution approach:

Input:

  • nums1 = [1, 1, 3, 2]
  • nums2 = [2, 3]
  • nums3 = [3]

Step 1: Convert arrays to sets

  • s1 = {1, 2, 3} (duplicates removed from nums1)
  • s2 = {2, 3}
  • s3 = {3}

Step 2: Check each number from 1 to 100

Let's trace through the first few relevant numbers:

  • i = 1:

    • (1 in s1) + (1 in s2) + (1 in s3) = True + False + False = 1 + 0 + 0 = 1
    • Count is 1, so 1 is NOT included (appears in only one array)
  • i = 2:

    • (2 in s1) + (2 in s2) + (2 in s3) = True + True + False = 1 + 1 + 0 = 2
    • Count is 2, so 2 IS included (appears in nums1 and nums2)
  • i = 3:

    • (3 in s1) + (3 in s2) + (3 in s3) = True + True + True = 1 + 1 + 1 = 3
    • Count is 3, so 3 IS included (appears in all three arrays)
  • i = 4 through i = 100:

    • All return count of 0, so none are included

Step 3: Build result The list comprehension collects all numbers where the count > 1:

  • Result: [2, 3]

Why this works:

  • Number 1 only appears in nums1, so it's excluded
  • Number 2 appears in both nums1 and nums2 (count = 2), so it's included
  • Number 3 appears in all three arrays (count = 3), so it's included
  • The duplicate 1 in nums1 doesn't affect the result since we use sets

Solution Implementation

1class Solution:
2    def twoOutOfThree(
3        self, nums1: List[int], nums2: List[int], nums3: List[int]
4    ) -> List[int]:
5        # Convert each list to a set to get unique elements from each array
6        set1 = set(nums1)
7        set2 = set(nums2)
8        set3 = set(nums3)
9      
10        # Find all integers that appear in at least two of the three arrays
11        # Using boolean addition: (i in set1) returns 1 if True, 0 if False
12        # If the sum is greater than 1, the number appears in at least 2 arrays
13        result = []
14        for i in range(1, 101):
15            count = (i in set1) + (i in set2) + (i in set3)
16            if count > 1:
17                result.append(i)
18      
19        return result
20
1class Solution {
2    /**
3     * Finds all integers that appear in at least two out of three arrays.
4     * 
5     * @param nums1 First array of integers
6     * @param nums2 Second array of integers  
7     * @param nums3 Third array of integers
8     * @return List of integers that appear in at least 2 arrays
9     */
10    public List<Integer> twoOutOfThree(int[] nums1, int[] nums2, int[] nums3) {
11        // Convert each array to presence arrays (0 or 1 for each possible value)
12        int[] presenceArray1 = createPresenceArray(nums1);
13        int[] presenceArray2 = createPresenceArray(nums2);
14        int[] presenceArray3 = createPresenceArray(nums3);
15      
16        List<Integer> result = new ArrayList<>();
17      
18        // Check each possible value from 1 to 100
19        for (int value = 1; value <= 100; value++) {
20            // Count how many arrays contain this value
21            int arrayCount = presenceArray1[value] + presenceArray2[value] + presenceArray3[value];
22          
23            // If value appears in at least 2 arrays, add to result
24            if (arrayCount > 1) {
25                result.add(value);
26            }
27        }
28      
29        return result;
30    }
31
32    /**
33     * Creates a presence array where index represents the value
34     * and element is 1 if value exists in the input array, 0 otherwise.
35     * 
36     * @param nums Input array of integers
37     * @return Presence array of size 101 (to handle values 1-100)
38     */
39    private int[] createPresenceArray(int[] nums) {
40        int[] presenceArray = new int[101];
41      
42        // Mark presence of each number in the array
43        for (int number : nums) {
44            presenceArray[number] = 1;
45        }
46      
47        return presenceArray;
48    }
49}
50
1class Solution {
2public:
3    vector<int> twoOutOfThree(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3) {
4        // Lambda function to convert array to presence indicator array
5        // Returns a vector where index i is 1 if value i exists in nums, 0 otherwise
6        auto getPresenceArray = [](vector<int>& nums) {
7            vector<int> presence(101, 0);  // Initialize with 0s, indices 0-100
8            for (int& value : nums) {
9                presence[value] = 1;  // Mark as present
10            }
11            return presence;
12        };
13      
14        // Get presence arrays for all three input arrays
15        auto presence1 = getPresenceArray(nums1);
16        auto presence2 = getPresenceArray(nums2);
17        auto presence3 = getPresenceArray(nums3);
18      
19        // Result vector to store values that appear in at least 2 arrays
20        vector<int> result;
21      
22        // Check each possible value from 1 to 100
23        for (int i = 1; i <= 100; ++i) {
24            // Count how many arrays contain value i
25            int appearanceCount = presence1[i] + presence2[i] + presence3[i];
26          
27            // If value appears in at least 2 arrays, add to result
28            if (appearanceCount >= 2) {
29                result.emplace_back(i);
30            }
31        }
32      
33        return result;
34    }
35};
36
1/**
2 * Finds all distinct values that appear in at least two out of three arrays
3 * @param nums1 - First array of numbers
4 * @param nums2 - Second array of numbers  
5 * @param nums3 - Third array of numbers
6 * @returns Array containing values that appear in at least 2 arrays
7 */
8function twoOutOfThree(nums1: number[], nums2: number[], nums3: number[]): number[] {
9    // Initialize frequency counter array for values 0-100
10    const frequencyCounter: number[] = new Array(101).fill(0);
11  
12    // Count unique occurrences from first array
13    const uniqueNums1: Set<number> = new Set(nums1);
14    uniqueNums1.forEach((value: number) => {
15        frequencyCounter[value]++;
16    });
17  
18    // Count unique occurrences from second array
19    const uniqueNums2: Set<number> = new Set(nums2);
20    uniqueNums2.forEach((value: number) => {
21        frequencyCounter[value]++;
22    });
23  
24    // Count unique occurrences from third array
25    const uniqueNums3: Set<number> = new Set(nums3);
26    uniqueNums3.forEach((value: number) => {
27        frequencyCounter[value]++;
28    });
29  
30    // Collect values that appear in at least 2 arrays
31    const result: number[] = [];
32    frequencyCounter.forEach((count: number, index: number) => {
33        if (count >= 2) {
34            result.push(index);
35        }
36    });
37  
38    return result;
39}
40

Time and Space Complexity

The time complexity is O(n₁ + n₂ + n₃ + 100) which simplifies to O(n₁ + n₂ + n₃) since 100 is a constant. The creation of each set takes O(n₁), O(n₂), and O(n₃) time respectively. The list comprehension iterates through the range 1 to 100 (constant time), and for each number, it performs three set membership checks (each O(1) on average). Therefore, the overall time complexity is O(n₁ + n₂ + n₃).

The space complexity is O(n₁ + n₂ + n₃). This accounts for the storage required by the three sets s1, s2, and s3, which in the worst case contain all unique elements from their respective input arrays. The output list takes at most O(100) = O(1) space since there are at most 100 possible values. Therefore, the overall space complexity is O(n₁ + n₂ + n₃).

Here, n₁, n₂, n₃ are the lengths of the arrays nums1, nums2, and nums3, respectively.

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

Common Pitfalls

1. Assuming Fixed Value Range Without Verification

The current solution assumes values are between 1 and 100, which could break if the problem constraints change or if negative numbers or values outside this range exist.

Problem Example:

nums1 = [1, 2, 200]  # Contains 200, outside assumed range
nums2 = [2, 3, 200]
nums3 = [3]
# Current solution would miss 200, even though it appears in 2 arrays

Solution: Instead of hardcoding the range, dynamically determine it from the actual values:

def twoOutOfThree(self, nums1, nums2, nums3):
    set1, set2, set3 = set(nums1), set(nums2), set(nums3)
  
    # Get all unique values across all arrays
    all_values = set1 | set2 | set3
  
    result = []
    for num in all_values:
        count = (num in set1) + (num in set2) + (num in set3)
        if count > 1:
            result.append(num)
  
    return result

2. Inefficient Set Intersection Approach

Some might attempt using set intersections directly, but this misses values that appear in exactly 2 arrays:

Incorrect Approach:

# This only finds values in ALL THREE arrays
result = set(nums1) & set(nums2) & set(nums3)  # Wrong!

Correct Alternative Using Set Operations:

def twoOutOfThree(self, nums1, nums2, nums3):
    set1, set2, set3 = set(nums1), set(nums2), set(nums3)
  
    # Find all pairwise intersections
    in_1_and_2 = set1 & set2
    in_1_and_3 = set1 & set3
    in_2_and_3 = set2 & set3
  
    # Union all pairwise intersections
    return list(in_1_and_2 | in_1_and_3 | in_2_and_3)

3. Not Handling Duplicates Within Individual Arrays

Forgetting to convert arrays to sets first could lead to incorrect counting if duplicates exist within a single array:

Problem Example:

nums1 = [1, 1, 1]  # 1 appears 3 times in nums1
nums2 = [2]
nums3 = [3]
# Without sets, might incorrectly think 1 appears in "multiple" arrays

The original solution correctly handles this by converting to sets first, ensuring each value is counted only once per array.

Discover Your Strengths and Weaknesses: Take Our 3-Minute Quiz to Tailor Your Study Plan:

What does the following code do?

1def f(arr1, arr2):
2  i, j = 0, 0
3  new_arr = []
4  while i < len(arr1) and j < len(arr2):
5      if arr1[i] < arr2[j]:
6          new_arr.append(arr1[i])
7          i += 1
8      else:
9          new_arr.append(arr2[j])
10          j += 1
11  new_arr.extend(arr1[i:])
12  new_arr.extend(arr2[j:])
13  return new_arr
14
1public static List<Integer> f(int[] arr1, int[] arr2) {
2  int i = 0, j = 0;
3  List<Integer> newArr = new ArrayList<>();
4
5  while (i < arr1.length && j < arr2.length) {
6      if (arr1[i] < arr2[j]) {
7          newArr.add(arr1[i]);
8          i++;
9      } else {
10          newArr.add(arr2[j]);
11          j++;
12      }
13  }
14
15  while (i < arr1.length) {
16      newArr.add(arr1[i]);
17      i++;
18  }
19
20  while (j < arr2.length) {
21      newArr.add(arr2[j]);
22      j++;
23  }
24
25  return newArr;
26}
27
1function f(arr1, arr2) {
2  let i = 0, j = 0;
3  let newArr = [];
4  
5  while (i < arr1.length && j < arr2.length) {
6      if (arr1[i] < arr2[j]) {
7          newArr.push(arr1[i]);
8          i++;
9      } else {
10          newArr.push(arr2[j]);
11          j++;
12      }
13  }
14  
15  while (i < arr1.length) {
16      newArr.push(arr1[i]);
17      i++;
18  }
19  
20  while (j < arr2.length) {
21      newArr.push(arr2[j]);
22      j++;
23  }
24  
25  return newArr;
26}
27

Recommended Readings

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

Load More