LeetCode 350. Intersection of Two Arrays II
原题链接在这里:https://leetcode.com/problems/intersection-of-two-arrays-ii/
题目:
Given two arrays, write a function to compute their intersection.
Example:
Given nums1 = [1, 2, 2, 1]
, nums2 = [2, 2]
, return [2, 2]
.
Note:
- Each element in the result should appear as many times as it shows in both arrays.
- The result can be in any order.
Follow up:
- What if the given array is already sorted? How would you optimize your algorithm?
- What if nums1's size is small compared to nums2's size? Which algorithm is better?
- What if elements of nums2 are stored on disk, and the memory is limited such that you cannot load all elements into the memory at once?
题解:
可以使用双指针.
Time Complexity: O(nlogn). Space: O(1).
AC Java:
1 public class Solution { 2 public int[] intersect(int[] nums1, int[] nums2) { 3 Arrays.sort(nums1); 4 Arrays.sort(nums2); 5 int i = 0; 6 int j = 0; 7 List<Integer> res = new ArrayList<Integer>(); 8 while(i<nums1.length && j<nums2.length){ 9 if(nums1[i] < nums2[j]){ 10 i++; 11 }else if(nums1[i] > nums2[j]){ 12 j++; 13 }else{ 14 res.add(nums1[i]); 15 i++; 16 j++; 17 } 18 } 19 20 int [] resArr = new int[res.size()]; 21 int k = 0; 22 for(int num : res){ 23 resArr[k++] = num; 24 } 25 return resArr; 26 } 27 }
AC C++:
1 class Solution { 2 public: 3 vector<int> intersect(vector<int>& nums1, vector<int>& nums2) { 4 vector<int> res; 5 sort(nums1.begin(), nums1.end()); 6 sort(nums2.begin(), nums2.end()); 7 int len1 = nums1.size(); 8 int len2 = nums2.size(); 9 int i = 0; 10 int j = 0; 11 while(i < len1 && j < len2){ 12 if(nums1[i] < nums2[j]){ 13 i++; 14 }else if(nums1[i] > nums2[j]){ 15 j++; 16 }else{ 17 res.push_back(nums1[i]); 18 i++; 19 j++; 20 } 21 } 22 23 return res; 24 } 25 };
Could use HashMap as well.
Time Complexity: O(m + n).
Space: O(Math.min(m, n)).
AC Java:
1 class Solution { 2 public int[] intersect(int[] nums1, int[] nums2) { 3 if(nums1 == null || nums2 == null){ 4 return new int[0]; 5 } 6 7 HashMap<Integer, Integer> hm = new HashMap<>(); 8 for(int num : nums1){ 9 hm.put(num, hm.getOrDefault(num, 0) + 1); 10 } 11 12 List<Integer> res = new ArrayList<>(); 13 for(int num : nums2){ 14 if(hm.containsKey(num)){ 15 res.add(num); 16 if(hm.get(num) == 1){ 17 hm.remove(num); 18 }else{ 19 hm.put(num, hm.get(num) - 1); 20 } 21 } 22 } 23 24 int [] resArr = new int[res.size()]; 25 int i = 0; 26 for(int num : res){ 27 resArr[i++] = num; 28 } 29 30 return resArr; 31 } 32 }
AC C++:
1 class Solution { 2 public: 3 vector<int> intersect(vector<int>& nums1, vector<int>& nums2) { 4 vector<int> res; 5 unordered_map<int, int> map; 6 for(int num : nums1){ 7 map[num]++; 8 } 9 10 for(int num : nums2){ 11 if(map[num] > 0){ 12 res.push_back(num); 13 map[num]--; 14 } 15 } 16 17 return res; 18 } 19 };
Follow up 2 nums1 length is smaller. 用双指针先sort两个array明显没有利用到num1.length小的特性. 若是用HashMap来记录num1每个element出现频率再iterate nums2, 那么Time Complexity: O(m + n), m = nums1.length, n = num2.length. Space: O(m).
或者sort nums1 再对每一个num2的element在 sorted nums1上做 binary search. Time Complexity: O(mlogm + nlogm). Space: O(1).
由此可见,当m很小时,用HashMap和binary search就是time和space的trade off.
Follow up 3 nums2 is sorted but too big for memory. I/O的操作很贵,所以首先想到的是避免I/O的次数。
若是nums1可以全部load到memory上, 先sort nums1再把nums2从小到大分开load到memory来.
if load进来这一段最大值, 也就是最后一个值<nums1[0] 或者 load进来这一段最小值, 也就是第一个值>nums1[nums1.length-1]可以直接跳过, load下一段. else load进来这一段 和 sorted nums1做双指针.
若是nums1也太大了,就先external sort nums1, 在分开load进来nums1一段和nums2一段做双指针.