Loading problems...
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.
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:
textfor 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.
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:
nums1[i] is smaller than nums2[j], we know for certain that nums1[i] cannot equal nums2[j] or any subsequent element in nums2 (since nums2 is sorted). Therefore, we must increment index i to find a larger candidate.nums1[i] equals nums2[j], we have found an intersection. We record it and verify uniqueness.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.

Let's trace nums1 = [4, 9, 5] and nums2 = [9, 4, 9, 8, 4].
nums1 becomes [4, 5, 9]nums2 becomes [4, 4, 8, 9, 9]i = 0, j = 0, result = []nums1[0] (4) and nums2[0] (4).result.i to 1, j to 1.result = [4]nums1[1] (5) and nums2[1] (4).j to 2.nums1[1] (5) and nums2[2] (8).i to 2.nums1[2] (9) and nums2[2] (8).j to 3.nums1[2] (9) and nums2[3] (9).i to 3, j to 4.result = [4, 9]i is now 3, which equals the length of nums1. The loop terminates. Return [4, 9].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.
cpp#include <vector> #include <algorithm> class Solution { public: std::vector<int> intersection(std::vector<int>& nums1, std::vector<int>& nums2) { // Step 1: Sort both arrays std::sort(nums1.begin(), nums1.end()); std::sort(nums2.begin(), nums2.end()); std::vector<int> result; int i = 0; // Pointer for nums1 int j = 0; // Pointer for nums2 // Step 2: Traverse with two pointers while (i < nums1.size() && j < nums2.size()) { if (nums1[i] < nums2[j]) { i++; } else if (nums1[i] > nums2[j]) { j++; } else { // Found intersection // Ensure uniqueness: add only if result is empty or last element is different if (result.empty() || result.back() != nums1[i]) { result.push_back(nums1[i]); } i++; j++; } } return result; } };
javaimport java.util.Arrays; import java.util.ArrayList; import java.util.List; class Solution { public int[] intersection(int[] nums1, int[] nums2) { // Step 1: Sort both arrays Arrays.sort(nums1); Arrays.sort(nums2); List<Integer> resultList = new ArrayList<>(); int i = 0; int j = 0; // Step 2: Traverse with two pointers while (i < nums1.length && j < nums2.length) { if (nums1[i] < nums2[j]) { i++; } else if (nums1[i] > nums2[j]) { j++; } else { // Found intersection // Handle uniqueness if (resultList.isEmpty() || resultList.get(resultList.size() - 1) != nums1[i]) { resultList.add(nums1[i]); } i++; j++; } } // Convert List to array int[] result = new int[resultList.size()]; for (int k = 0; k < resultList.size(); k++) { result[k] = resultList.get(k); } return result; } }
pythonclass Solution: def intersection(self, nums1: list[int], nums2: list[int]) -> list[int]: # Step 1: Sort both arrays nums1.sort() nums2.sort() result = [] i, j = 0, 0 # Step 2: Traverse with two pointers while i < len(nums1) and j < len(nums2): if nums1[i] < nums2[j]: i += 1 elif nums1[i] > nums2[j]: j += 1 else: # Found intersection # Handle uniqueness if not result or result[-1] != nums1[i]: result.append(nums1[i]) i += 1 j += 1 return result
Time Complexity: The sorting step dominates the complexity. Once sorted, the two-pointer traversal takes linear time in the worst case. Thus, the total time complexity is determined by the sorting algorithm used.
Space Complexity: or This depends on the implementation of the sorting algorithm. Most language-standard sorting algorithms use stack space (e.g., QuickSort variants) or buffer space (e.g., MergeSort). We ignore the space required for the output array as per standard complexity analysis conventions.
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:
Understanding how sorting enables deterministic pointer movement is key to solving these popular interview questions.
Q: Why does my solution contain duplicate numbers?
Mistake: Failing to check if the number has already been added to the result list.
Why: The problem statement explicitly requires unique elements, but the input arrays may contain duplicates (e.g., nums1 = [2, 2], nums2 = [2, 2]).
Consequence: The output [2, 2] is incorrect; it should be [2].
Q: Why am I getting an IndexOutOfBoundsException?
Mistake: Incrementing pointers inside the loop without checking bounds, or accessing result[-1] when result is empty.
Why: Logic errors often occur when advancing i and j multiple times in one iteration or forgetting to check if the result list isEmpty before checking the last element.
Runtime error causing the test cases to crash.
Q: Why is my solution slower than expected?
Mistake: Using .contains() on a List inside the loop to check for uniqueness.
Why: The .contains() method on a List is . Doing this inside the loop makes the total complexity .
Consequence: Efficiency failure. By sorting first, checking uniqueness only requires comparing against the last added element, which is .