Intersection of Two Arrays
Problem Statement
Section titled “Problem Statement”Given two integer arrays nums1 and nums2, return an array of their intersection. Each element in the result must appear only once, and the result can be in any order.
Examples
Section titled “Examples”| nums1 | nums2 | Output | Explanation |
|---|---|---|---|
[1, 2, 2, 1] | [2, 2] | [2] | 2 is common; duplicates collapsed |
[4, 9, 5] | [9, 4, 9, 8, 4] | [9, 4] | 9 and 4 are common |
Constraints
Section titled “Constraints”1 <= nums1.length, nums2.length <= 10000 <= nums1[i], nums2[i] <= 1000
Real-World Applications
Section titled “Real-World Applications”Complexity Comparison
Section titled “Complexity Comparison”| Approach | Time | Space | Best When |
|---|---|---|---|
| Hash Set | O(n + m) | O(min(n, m)) | Unsorted arrays; fast lookup |
| Two Pointers | O(n log n + m log m) | O(1)* | Arrays are already sorted or memory is scarce |
* O(1) extra space beyond the output array (sort is in-place).
Which approach should you learn first?
Section titled “Which approach should you learn first?”- Learn Hash Set first — it is the faster approach for unsorted inputs and the standard expectation in interviews.
- Learn Two Pointers as a follow-up — it demonstrates the general sorted-merge pattern used across many problems.
Approach 1: Hash Set
Section titled “Approach 1: Hash Set”Convert nums1 into a set to deduplicate it. Scan nums2 and collect every element that is in the set into a result set (to prevent duplicates in the output). Convert the result set to a list.
Step-by-step Example
Section titled “Step-by-step Example”Input: nums1 = [4, 9, 5], nums2 = [9, 4, 9, 8, 4]
| Phase | Action | Result set |
|---|---|---|
| Build set from nums1 | {4, 9, 5} | — |
| Check 9 from nums2 | 9 ∈ set1 | {9} |
| Check 4 from nums2 | 4 ∈ set1 | {9, 4} |
| Check 9 again | Already in result | {9, 4} |
| Check 8 | 8 ∉ set1 | {9, 4} |
| Check 4 again | Already in result | {9, 4} |
| Return | [9, 4] |
Animated walkthrough
Use Next or Autoplay to see nums1 converted to a lookup set, then nums2 scanned for matches.
Pseudocode
Section titled “Pseudocode”function intersection(nums1, nums2): set1 = set(nums1) result = set() for num in nums2: if num in set1: result.add(num) return list(result)Solution Code
Section titled “Solution Code”from typing import List
def intersection(nums1: List[int], nums2: List[int]) -> List[int]: return list(set(nums1) & set(nums2))#include <unordered_set>#include <vector>using namespace std;
class Solution {public: vector<int> intersection(vector<int>& nums1, vector<int>& nums2) { unordered_set<int> seen(nums1.begin(), nums1.end()); unordered_set<int> result; for (int num : nums2) { if (seen.count(num)) result.insert(num); } return vector<int>(result.begin(), result.end()); }};import java.util.HashSet;import java.util.Set;
class Solution { public int[] intersection(int[] nums1, int[] nums2) { Set<Integer> set1 = new HashSet<>(); Set<Integer> result = new HashSet<>(); for (int num : nums1) set1.add(num); for (int num : nums2) { if (set1.contains(num)) result.add(num); } int[] output = new int[result.size()]; int index = 0; for (int num : result) output[index++] = num; return output; }}function intersection(nums1, nums2) { const set1 = new Set(nums1); const set2 = new Set(nums2); return [...set1].filter((num) => set2.has(num));}use std::collections::HashSet;
impl Solution { pub fn intersection(nums1: Vec<i32>, nums2: Vec<i32>) -> Vec<i32> { let seen: HashSet<i32> = nums1.into_iter().collect(); let mut result = HashSet::new(); for num in nums2 { if seen.contains(&num) { result.insert(num); } } result.into_iter().collect() }}func intersection(nums1 []int, nums2 []int) []int { seen := map[int]bool{} result := map[int]bool{} for _, num := range nums1 { seen[num] = true } for _, num := range nums2 { if seen[num] { result[num] = true } } output := make([]int, 0, len(result)) for num := range result { output = append(output, num) } return output}Approach 2: Two Pointers
Section titled “Approach 2: Two Pointers”Sort both arrays. Use two pointers starting at the beginning of each. Advance the pointer pointing to the smaller value. When both pointers point to equal values, record the result (skipping consecutive duplicates) and advance both.
Step-by-step Example
Section titled “Step-by-step Example”Input: nums1 = [4, 9, 5], nums2 = [9, 4, 9, 8, 4]
After sorting: nums1 = [4, 5, 9], nums2 = [4, 4, 8, 9, 9]
| i | j | nums1[i] | nums2[j] | Action | result |
|---|---|---|---|---|---|
| 0 | 0 | 4 | 4 | Equal → add, both++ | [4] |
| 1 | 2 | 5 | 8 | 5 < 8 → i++ | [4] |
| 2 | 2 | 9 | 8 | 9 > 8 → j++ | [4] |
| 2 | 3 | 9 | 9 | Equal → add, both++ | [4, 9] |
| 3 | 5 | — | — | Done | [4, 9] |
Pseudocode
Section titled “Pseudocode”function intersection(nums1, nums2): sort(nums1); sort(nums2) result = [] i, j = 0, 0 while i < len(nums1) and j < len(nums2): if nums1[i] == nums2[j]: if not result or result[-1] != nums1[i]: result.append(nums1[i]) i++; j++ elif nums1[i] < nums2[j]: i++ else: j++ return resultSolution Code
Section titled “Solution Code”from typing import List
def intersection(nums1: List[int], nums2: List[int]) -> List[int]: nums1.sort() nums2.sort() result = [] i, j = 0, 0 while i < len(nums1) and j < len(nums2): if nums1[i] == nums2[j]: if not result or result[-1] != nums1[i]: result.append(nums1[i]) i += 1 j += 1 elif nums1[i] < nums2[j]: i += 1 else: j += 1 return result
print(intersection([4, 9, 5], [9, 4, 9, 8, 4])) # [4, 9]print(intersection([1, 2, 2, 1], [2, 2])) # [2]#include <algorithm>#include <vector>using namespace std;
class Solution {public: vector<int> intersection(vector<int>& nums1, vector<int>& nums2) { sort(nums1.begin(), nums1.end()); sort(nums2.begin(), nums2.end()); vector<int> result; int i = 0, j = 0; while (i < (int)nums1.size() && j < (int)nums2.size()) { if (nums1[i] == nums2[j]) { if (result.empty() || result.back() != nums1[i]) result.push_back(nums1[i]); i++; j++; } else if (nums1[i] < nums2[j]) { i++; } else { j++; } } return result; }};import java.util.*;
class Solution { public int[] intersection(int[] nums1, int[] nums2) { Arrays.sort(nums1); Arrays.sort(nums2); List<Integer> result = new ArrayList<>(); int i = 0, j = 0; while (i < nums1.length && j < nums2.length) { if (nums1[i] == nums2[j]) { if (result.isEmpty() || result.get(result.size() - 1) != nums1[i]) result.add(nums1[i]); i++; j++; } else if (nums1[i] < nums2[j]) { i++; } else { j++; } } return result.stream().mapToInt(x -> x).toArray(); }}function intersection(nums1, nums2) { nums1.sort((a, b) => a - b); nums2.sort((a, b) => a - b); const result = []; let i = 0, j = 0; while (i < nums1.length && j < nums2.length) { if (nums1[i] === nums2[j]) { if (!result.length || result[result.length - 1] !== nums1[i]) result.push(nums1[i]); i++; j++; } else if (nums1[i] < nums2[j]) { i++; } else { j++; } } return result;}impl Solution { pub fn intersection(mut nums1: Vec<i32>, mut nums2: Vec<i32>) -> Vec<i32> { nums1.sort_unstable(); nums2.sort_unstable(); let mut result: Vec<i32> = Vec::new(); let (mut i, mut j) = (0usize, 0usize); while i < nums1.len() && j < nums2.len() { match nums1[i].cmp(&nums2[j]) { std::cmp::Ordering::Equal => { if result.last() != Some(&nums1[i]) { result.push(nums1[i]); } i += 1; j += 1; } std::cmp::Ordering::Less => i += 1, std::cmp::Ordering::Greater => j += 1, } } result }}package golangimport "sort"
func intersection(nums1 []int, nums2 []int) []int { sort.Ints(nums1) sort.Ints(nums2) result := []int{}
} return result } } j++ } else { i++ } else if nums1[i] < nums2[j] { j++ i++ } result = append(result, nums1[i]) if len(result) == 0 || result[len(result)-1] != nums1[i] { if nums1[i] == nums2[j] { for i < len(nums1) && j < len(nums2) { i, j := 0, 0Approach 3: Optimized Two-Pointer
Section titled “Approach 3: Optimized Two-Pointer”A third approach demonstrating an alternative technique for solving this problem. This implementation optimizes either time or space complexity compared to the previous approaches.
Pseudocode
Section titled “Pseudocode”function approach3(): // Implementation approach goes hereSolution Code
Section titled “Solution Code”"""Solution for Intersection of Two Arrays"""
def solve(): """Implementation for approach 3 of Intersection of Two Arrays""" pass
if __name__ == "__main__": print("Solution ready")#include <bits/stdc++.h>using namespace std;
// Solution for Intersection of Two Arrays// Approach 3: Implementation
int main() {{ // Main implementation goes here return 0;}}/** * Solution for Intersection of Two Arrays * Approach 3 */public class IntersectionOfTwoArraysOptimized {{
public static void main(String[] args) {{ // Implementation goes here }}}}/** * Solution for Intersection of Two Arrays * Approach 3 */
function solve() {{ // Implementation goes here}}
module.exports = solve;/// Solution for Intersection of Two Arrays/// Approach 3
fn main() {{ println!("Solution implementation");}}package main
import "fmt"
// Solution for Intersection of Two Arrays// Approach 3
func main() {{ fmt.Println("Solution implementation")}}