Editorial
Core insight
Intersection of Two Arrays · Two Pointers
Core Insight for Intersection of Two Arrays
The key intuition for solving LeetCode 349 efficiently lies in the properties of sorted arrays.
If nums1 and nums2 are unsorted, we have no context about where a matching number might be located. However, if we sort both arrays first, we establish a monotonic order. This allows us to apply the Two Pointer strategy:
- Relative Magnitude: If
nums1[i]is smaller thannums2[j], we know for certain thatnums1[i]cannot equalnums2[j]or any subsequent element innums2(sincenums2is sorted). Therefore, we must increment indexito find a larger candidate. - Equality: If
nums1[i]equalsnums2[j], we have found an intersection. We record it and verify uniqueness. - Invariant: At any step, we only discard elements that are strictly smaller than the current candidate in the opposing array, ensuring we never miss a valid intersection.
Visual Description: Imagine two horizontal number lines representing the sorted arrays. We place a marker (pointer) at the start of each line. We compare the values under the markers. The marker pointing to the smaller value moves one step to the right. If they are equal, we record the value and move both markers. This process continues until one marker runs off the end of its line.

Deep dive
Full breakdown
Full reasoning, pitfalls, and implementation flow
LeetCode 349: Intersection of Two Arrays Solution & Explanation
Problem Overview
TL;DR: Sort both input arrays and iterate through them simultaneously using two pointers to identify and collect unique common elements.
The Intersection of Two Arrays problem requires us to find common elements between two integer arrays, nums1 and nums2. The resulting array must contain unique elements only, meaning if a number appears multiple times in the intersection, it should only appear once in the output. The order of the result does not matter. This is a fundamental LeetCode 349 solution scenario often used to test understanding of array manipulation and memory efficiency.
Brute Force Approach for Intersection of Two Arrays
The naive approach involves iterating through every element of the first array and, for each element, scanning the entire second array to check for a match. To ensure uniqueness, we would store matches in a set (or check the result list before adding).
Pseudo-code:
result = empty set
for each x in nums1:
for each y in nums2:
if x == y:
add x to result
return list(result)Time Complexity: , where and are the lengths of the arrays. For every element in , we scan . Why it fails: While this might pass for small constraints (like ), it is inefficient. In an interview context, an quadratic solution is rarely considered acceptable when linear or log-linear solutions exist. It demonstrates a lack of algorithmic optimization knowledge.
Algorithm Strategy: Two Pointer Patterns
- Sort Inputs: Begin by sorting both
nums1andnums2in ascending order. This is a prerequisite for the two-pointer logic to work. - Initialize Pointers: Set two pointers,
iandj, to 0. These correspond to the indices ofnums1andnums2respectively. - Traverse and Compare: Enter a loop that continues as long as both
iandjare within the bounds of their respective arrays.- If
nums1[i] < nums2[j]: Incrementi. - If
nums1[i] > nums2[j]: Incrementj. - If
nums1[i] == nums2[j]: This is an intersection. Check if the result array is empty or if the last added element is different fromnums1[i](to ensure uniqueness). If unique, add it to the result. Increment bothiandj.
- If
- Return: Convert the result collection to the required return type (array/vector).
Execution Flow
Let's trace nums1 = [4, 9, 5] and nums2 = [9, 4, 9, 8, 4].
- Sort:
nums1becomes[4, 5, 9]nums2becomes[4, 4, 8, 9, 9]
- State:
i = 0,j = 0,result = [] - Iteration 1:
- Compare
nums1[0](4) andnums2[0](4). - They are equal. Add 4 to
result. - Increment
ito 1,jto 1. result = [4]
- Compare
- Iteration 2:
- Compare
nums1[1](5) andnums2[1](4). - 5 > 4. Increment
jto 2.
- Compare
- Iteration 3:
- Compare
nums1[1](5) andnums2[2](8). - 5 < 8. Increment
ito 2.
- Compare
- Iteration 4:
- Compare
nums1[2](9) andnums2[2](8). - 9 > 8. Increment
jto 3.
- Compare
- Iteration 5:
- Compare
nums1[2](9) andnums2[3](9). - They are equal. Check uniqueness. 9 != last element (4). Add 9.
- Increment
ito 3,jto 4. result = [4, 9]
- Compare
- Termination:
iis now 3, which equals the length ofnums1. The loop terminates. Return[4, 9].
Proof of Correctness
The algorithm relies on the monotonicity of the sorted arrays. When nums1[i] < nums2[j], the value nums1[i] cannot exist in nums2 at any index k >= j because nums2 is sorted in ascending order. Therefore, skipping nums1[i] is safe. The same logic applies when nums2[j] < nums1[i]. When values are equal, we capture the intersection. Since we iterate through the sorted arrays linearly and only skip elements that cannot possibly match, the algorithm is guaranteed to find all common elements. The uniqueness check ensures adherence to the problem constraints.
Pattern Reuse Notes
The Two Pointer pattern used here is highly versatile. The following problems share the same underlying logic of manipulating pointers on sorted arrays or converging boundaries:
- LeetCode 11: Container With Most Water (Converging pointers to optimize area)
- LeetCode 15: 3Sum (Sorting + Two Pointers to find triplets)
- LeetCode 16: 3Sum Closest (Variation of 3Sum using distance comparison)
- LeetCode 18: 4Sum (Extension of 3Sum logic)
Understanding how sorting enables deterministic pointer movement is key to solving these popular interview questions.
Feynman coach · Before you peek at the code
Can you explain the core insight in your own words?
If you can explain it before reading code, you’re far more likely to recall it under interview pressure.
Reference Implementation
C++ Solution for LeetCode 349
1#include <vector>
2#include <algorithm>
3
4class Solution {
5public:
6 std::vector<int> intersection(std::vector<int>& nums1, std::vector<int>& nums2) {
7 // Step 1: Sort both arrays
8 std::sort(nums1.begin(), nums1.end());
9 std::sort(nums2.begin(), nums2.end());
10
11 std::vector<int> result;
12 int i = 0; // Pointer for nums1
13 int j = 0; // Pointer for nums2
14
15 // Step 2: Traverse with two pointers
16 while (i < nums1.size() && j < nums2.size()) {
17 if (nums1[i] < nums2[j]) {
18 i++;
19 } else if (nums1[i] > nums2[j]) {
20 j++;
21 } else {
22 // Found intersection
23 // Ensure uniqueness: add only if result is empty or last element is different
24 if (result.empty() || result.back() != nums1[i]) {
25 result.push_back(nums1[i]);
26 }
27 i++;
28 j++;
29 }
30 }
31
32 return result;
33 }
34};Java Solution for LeetCode 349
1import java.util.Arrays;
2import java.util.ArrayList;
3import java.util.List;
4
5class Solution {
6 public int[] intersection(int[] nums1, int[] nums2) {
7 // Step 1: Sort both arrays
8 Arrays.sort(nums1);
9 Arrays.sort(nums2);
10
11 List<Integer> resultList = new ArrayList<>();
12 int i = 0;
13 int j = 0;
14
15 // Step 2: Traverse with two pointers
16 while (i < nums1.length && j < nums2.length) {
17 if (nums1[i] < nums2[j]) {
18 i++;
19 } else if (nums1[i] > nums2[j]) {
20 j++;
21 } else {
22 // Found intersection
23 // Handle uniqueness
24 if (resultList.isEmpty() || resultList.get(resultList.size() - 1) != nums1[i]) {
25 resultList.add(nums1[i]);
26 }
27 i++;
28 j++;
29 }
30 }
31
32 // Convert List to array
33 int[] result = new int[resultList.size()];
34 for (int k = 0; k < resultList.size(); k++) {
35 result[k] = resultList.get(k);
36 }
37
38 return result;
39 }
40}Python Solution for LeetCode 349
1class Solution:
2 def intersection(self, nums1: list[int], nums2: list[int]) -> list[int]:
3 # Step 1: Sort both arrays
4 nums1.sort()
5 nums2.sort()
6
7 result = []
8 i, j = 0, 0
9
10 # Step 2: Traverse with two pointers
11 while i < len(nums1) and j < len(nums2):
12 if nums1[i] < nums2[j]:
13 i += 1
14 elif nums1[i] > nums2[j]:
15 j += 1
16 else:
17 # Found intersection
18 # Handle uniqueness
19 if not result or result[-1] != nums1[i]:
20 result.append(nums1[i])
21 i += 1
22 j += 1
23
24 return result