题目链接

题目描述

给定两个数组,编写一个函数来计算它们的交集。

示例

示例1:

输入:nums1 = [1,2,2,1], nums2 = [2,2] 输出:[2,2]

说明

  • 输出结果中每个元素出现的次数,应与元素在两个数组中出现次数的最小值一致。
  • 我们可以不考虑输出结果的顺序。

    思路

    思路1:排序+双指针

    可以看做0349-两个数组的交集的简化

    思路2:哈希表

    题目允许无序,可重复,因此我们可以使用 std::unorder_map 来完成这个题目。

    进阶

  1. 如果给定的数组已经排好序呢?你将如何优化你的算法?

答:使用双指针。

  1. 如果 nums1 的大小比 nums2 小很多,哪种方法更优?

答:对较短的数组进行哈希表的操作,哈希表的大小不会超过较短的数组的长度,减小空间的开销。

  1. 如果 nums2 的元素存储在磁盘上,内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?

答:不能一次性加载到内存中,则无法排序,只能采用思路2的方法。

题解

思路1:排序+双指针

  1. class Solution {
  2. public:
  3. vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
  4. sort(nums1.begin(), nums1.end());
  5. sort(nums2.begin(), nums2.end());
  6. int i = 0, j = 0;
  7. vector<int> ans;
  8. while (i < (int)nums1.size() && j < (int)nums2.size()) {
  9. if (nums1[i] == nums2[j]) {
  10. ans.emplace_back(nums1[i]);
  11. ++i;
  12. ++j;
  13. } else if (nums1[i] < nums2[j]) {
  14. ++i;
  15. } else {
  16. ++j;
  17. }
  18. }
  19. return ans;
  20. }
  21. };

思路2:哈希表

  1. class Solution {
  2. public:
  3. vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
  4. if (nums1.size() > nums2.size()) {
  5. return intersect(nums2, nums1);
  6. }
  7. unordered_map<int, int> count;
  8. vector<int> ans;
  9. for (int num : nums1) {
  10. ++count[num];
  11. }
  12. for (int num : nums2) {
  13. if (count.count(num) && count[num] > 0) {
  14. ans.emplace_back(num);
  15. --count[num];
  16. }
  17. }
  18. return ans;
  19. }
  20. };

复杂度分析

思路1:排序+双指针

  • 时间复杂度:0350-两个数组的交集II - 图1
  • 空间复杂度:0350-两个数组的交集II - 图2

    思路2:哈希表

  • 时间复杂度:0350-两个数组的交集II - 图3

  • 空间复杂度:0350-两个数组的交集II - 图4