题目链接:https://leetcode.com/problems/intersection-of-two-arrays/
题目大意:要求两个数组的交集(注意集合是不能含有重复的元素的)
方法1)
先对两个数组进行排序,设置两个指针pA和pB,分别指向这两个数组,比较nums1[pA]和nums[pB]
a. 如果想等,则为交集中的元素,++pA, ++pB
b. 如果nums[pA] < nums[pB],则++pA
c. 否则,++pB
注意数组中有重复的元素(实现代码中的小trick)
class Solution { public: vector<int> intersection(vector<int>& nums1, vector<int>& nums2) { sort(nums1.begin(), nums1.end()); sort(nums2.begin(), nums2.end()); int n1 = nums1.size(); int n2 = nums2.size(); int i = 0; int j = 0; vector<int> ans; while(i < n1 && j < n2) { while(i != 0 && nums1[i] == nums1[i-1] && i < n1) { ++i; } while(j != 0 && nums2[j] == nums2[j-1] && j < n2) { ++j; } if(i < n1 && j < n2) { if(nums1[i] == nums2[j]) { ans.push_back(nums1[i]); ++i; ++j; } else if(nums1[i] < nums2[j]) { ++i; } else { ++j; } } } return ans; } };
上述算法的时间复杂度为:
每一步的时间复杂度为O(n1log1), O(n2log2), (n1,n2)的最小值,最终的时间复杂度为O(n1log1)和O(n2log2)的最小值
方法2)
使用hash的方法来完成,因为题目当中没有要求交集中的数组是有序的
思路就不说了,直接看下面的代码吧
class Solution { public: vector<int> intersection(vector<int>& nums1, vector<int>& nums2) { int n1 = nums1.size(); int n2 = nums2.size(); unordered_set<int> sets; for(int i=0; i<n1; ++i) { if(sets.find(nums1[i]) == sets.end()) { sets.insert(nums1[i]); } } unordered_set<int> ans_sets; for(int i=0; i<n2; ++i) { if(sets.find(nums2[i]) != sets.end()) { ans_sets.insert(nums2[i]); } } vector<int> ans(ans_sets.begin(), ans_sets.end()); return ans; } };
题目II在I的基础上加上了条件:就是可以出现重复的元素,其实是更加简单了,只要去掉去重的语句即可
题目最后给出了3个问题:
- 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?
1)如果数组已经有序,上述算法中算法1)的时间复杂度就是min(n1, n2)
2) 如果n1 < n2, 上述算法1更好,因为算法2)要遍历所有的元素
3)可以把num1中的数组放到map中,map记录当前元素以及出现的次数,然后读文件,遍历num2中的元素,如果出现在map中就输出一次,同时次数减1