350. 两个数组的交集 II

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

示例 1:

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

示例 2:

输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [4,9]

说明:

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

进阶:

  • 如果给定的数组已经排好序呢?你将如何优化你的算法?
  • 如果 nums1 的大小比 nums2 小很多,哪种方法更优?
  • 如果 nums2 的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?

思路:

法一:

和版本I的第2种方法差不多,在版本I的法2基础上去掉删除重复元素的步骤就可以

代码:

class Solution {
public:
    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
        vector<int> rev;
        if(nums1.empty() ||nums2.empty())             //如果数组其中一个为空,直接返回空数组
            return rev;
        sort(nums1.begin(),nums1.end());                    //将数组1排序
        sort(nums2.begin(),nums2.end());                    //将数组2排序
        
        vector<int>::iterator n1=nums1.begin(),n2=nums2.begin();    //设定指针n1和n2
        while(n1<nums1.end() &&n2<nums2.end())                //在n1和n2不越界的条件下循环
        {
            if(*n1==*n2)                                       //*n1==*n2的情况
            {
                rev.push_back(*n1);
                n1++;
                n2++;
            }
            while(*n1>*n2 && n2<nums2.end())                   //*n1>*n2的情况
                n2++;
            while(*n1<*n2 &&n1<nums1.end() )                   //*n1<*n2的情况
                n1++;
        }
        return rev;
    }
};

法二:

由于要考虑 nums1 的大小比 nums2 小很多的情况,所以假设在这样的情况下,我们可以直接对nums1的每个元素遍历nums2,这样最差需要花费(nums1.size()*nums2.size())的时间

法三:

也是考虑 nums1 的大小比 nums2 小很多的情况

用一个map存数组1中元素的个数,将元素作为key,元素的个数作为value

然后遍历数组2,如果数组2中元素的映射大于等于1,则将元素放到要返回的数组,并将映射减1

代码:

class Solution {
public:
    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
        map<int,int> m;
        for(int i=0;i<nums1.size();i++)        //遍历数组1,将数组1中对应元素的的映射加1
        {
            m[nums1[i]]++;
        }                                      //最后得到的映射就是数组1中每个元素的数量
        vector<int> rev;
        for(int i=0;i<nums2.size();i++)        //遍历数组2
        {
            if(m[nums2[i]]>=1)                //映射大于等于1的情况
            {
                rev.push_back(nums2[i]);
                m[nums2[i]]--;
            }
        }
        return rev;
    }
};

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

法二和法三没得优化

对于法一,则是增强了它的数据规模处理性,使得在不能一次加载所有的元素到内存中这种情况下法一也可行

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

法一在此情况下会有多余的排序,比如说nums1的长度是1,nums2的长度是1000000,那么会浪费排序的时间

法二在此情况下就比较不错了,因为nums1的长度小,所以综合不会花很多时间,但法二仅是适用于这种情况,在其它情况下就是蛮力法,是很糟糕的

法三无论是在正常情况,还是在上面这种极端情况,速度都比较快的

所以总的来说,在上面这种极端情况下,法二和法三更优

 

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

对于法一,它需要对所有元素进行排序,所以不适用

对于法二和法三,数据的先后顺序对它们影响不大,所以它们可以先从内存取一部分数据,再处理数据,再取数据再处理,直到数据处理完为止

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值