Intersection of Two Arrays II
Multiset intersection — match each element with multiplicity using a counter.
3 min read
hash-map arrays
Problem#
Given two integer arrays, return their intersection as a multiset — each element appears as many times as it does in both. Result order doesn’t matter.
Examples#
nums1 = [1,2,2,1], nums2 = [2,2]→[2,2].nums1 = [4,9,5], nums2 = [9,4,9,8,4]→[4,9](or[9,4]).
Constraints#
1 <= nums.length <= 1000,0 <= nums[i] <= 1000.
Hints#
Hint
Count one array; walk the other and decrement on each match.
Approach#
Build counter for the smaller array. Walk the larger; if the counter has a positive count, emit and decrement.
Solution#
class Solution {public: vector<int> intersect(vector<int>& nums1, vector<int>& nums2) { if (nums1.size() > nums2.size()) return intersect(nums2, nums1); unordered_map<int,int> cnt; for (int v : nums1) ++cnt[v]; vector<int> ans; for (int v : nums2) { auto it = cnt.find(v); if (it != cnt.end() && it->second > 0) { ans.push_back(v); --it->second; } } return ans; }};func intersect(nums1 []int, nums2 []int) []int { if len(nums1) > len(nums2) { return intersect(nums2, nums1) } cnt := make(map[int]int) for _, v := range nums1 { cnt[v]++ } ans := []int{} for _, v := range nums2 { if c, ok := cnt[v]; ok && c > 0 { ans = append(ans, v) cnt[v]-- } } return ans}from typing import Listfrom collections import Counter
class Solution: def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]: if len(nums1) > len(nums2): return self.intersect(nums2, nums1) cnt = Counter(nums1) ans: List[int] = [] for v in nums2: if cnt[v] > 0: ans.append(v) cnt[v] -= 1 return ansfunction intersect(nums1, nums2) { if (nums1.length > nums2.length) return intersect(nums2, nums1); const cnt = new Map(); for (const v of nums1) cnt.set(v, (cnt.get(v) ?? 0) + 1); const ans = []; for (const v of nums2) { const c = cnt.get(v); if (c !== undefined && c > 0) { ans.push(v); cnt.set(v, c - 1); } } return ans;}class Solution { public int[] intersect(int[] nums1, int[] nums2) { if (nums1.length > nums2.length) return intersect(nums2, nums1); Map<Integer, Integer> cnt = new HashMap<>(); for (int v : nums1) cnt.merge(v, 1, Integer::sum); List<Integer> ans = new ArrayList<>(); for (int v : nums2) { Integer c = cnt.get(v); if (c != null && c > 0) { ans.add(v); cnt.put(v, c - 1); } } int[] out = new int[ans.size()]; for (int i = 0; i < ans.size(); i++) out[i] = ans.get(i); return out; }}function intersect(nums1: number[], nums2: number[]): number[] { if (nums1.length > nums2.length) return intersect(nums2, nums1); const cnt: Map<number, number> = new Map(); for (const v of nums1) cnt.set(v, (cnt.get(v) ?? 0) + 1); const ans: number[] = []; for (const v of nums2) { const c = cnt.get(v); if (c !== undefined && c > 0) { ans.push(v); cnt.set(v, c - 1); } } return ans;}Editorial#
Choosing the smaller array for the counter caps memory at O(min(N, M)). The decrement-on-match step enforces multiset semantics — without it the result would be set intersection.
Complexity#
- Time: O(N + M).
- Space: O(min(N, M)).
Concept revision#
Related#