【LeetCode & 剑指offer刷题】数组题10:Intersection of Two Arrays(系列)

【LeetCode & 剑指offer刷题】数组题10:Intersection of Two Arrays(系列)

【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)

349. Intersection of Two Arrays

Given two arrays, write a function to compute their intersection.
Example:
Given   nums1   =   [1, 2, 2, 1] ,   nums2   =   [2, 2] , return   [2] .
Note:
  • Each element in the result must be unique .
  • The result can be in any order.

 
/*
问题:求两个数组的交集(不能有重复的数)
方法一: hash 表法,用 set 避免重复
O(n) ,O(n)
*/
class Solution
{
public :
    vector < int > intersection ( vector < int >& nums1 , vector < int >& nums2 )
    {
        if ( nums1 . empty () || nums2 . empty ()) return {};
       
        unordered_set <int> m(nums1.begin(), nums1.end()); //vector转set,避免重复
        vector < int > res ;
        for ( auto a : nums2 )
        {
            if ( m . count ( a ))
            {
                res . push_back ( a );
                m . erase ( a );  //去除该数
            }           
        }
        return res ;
    }
};
/*
方法二:排序之后再找
用时间来换空间
O(nlogn),O(1)
*/
class Solution
{
public :
    vector < int > intersection ( vector < int >& nums1 , vector < int >& nums2 )
    {
        if ( nums1 . empty () || nums2 . empty ()) return {};
       
        vector < int > res ;
        int i = 0 , j = 0 ;
        sort ( nums1 . begin (), nums1 . end ());
        sort ( nums2 . begin (), nums2 . end ());
       
        while ( i < nums1 . size () && j < nums2 . size ()) // 从起始位置开始分别扫描两个数组
        {
            if (nums1[i] < nums2[j]) i++; //递增第一个数组的指针
            else if (nums1[i] > nums2[j]) j++; //递增第二个数组的指针
            else
            {
                if ( res . empty () || res . back () != nums1 [ i ]) //如果为空或者不重复时才push交集元素
                {
                    res . push_back ( nums1 [ i ]);
                }
                i ++; j++; //同时递增两个数组指针
            }
        }
        return res ;
    }
};
 
 
 
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?
/* 问题:计算两个数组的交集 ( 交集中元素与顺序无关,不是指公共子数组 )
可以返回重复的数
思考题 3
If only nums2 cannot fit in memory, put all elements of nums1 into a HashMap, read chunks of array that fit into the memory, and record the intersections.
If both nums1 and nums2 are so huge that neither fit into the memory, sort them individually (external sort), then read 2 elements from each array at a time in memory, record intersections.
*/
/*
* 方法一: hash
* 过程:构建 hash 表计数器,依 nums2 在计数器中出现的次数,如果出现了,就 push 元素,计数器对应值减一
* 分析: O(m+n),O(m)
*/
#include <unordered_map>
class Solution
{
public :
    vector < int > intersect ( vector < int >& nums1 , vector < int >& nums2 )
    {
        unordered_map < int , int > counter ;
        vector < int > res ;
        for ( int num : nums1 ) counter [ num ]++;   // 统计每个数的出现次数(首次调用 operator[] 以零初始化计数器
        for ( int num : nums2 )
        {
            if ( counter . find ( num ) != counter . end () && counter [ num ]>= 1 ) // 如果在 nums1 中找得到对应元素而且计数值大于 1 时,说明是交集的一部分
            {
                counter [ num ]--;
                res . push_back ( num );
            }
        }
        return res ;
    }
};
/*
* 方法二:排序之后再找
以时间换空间
* 分析: O mlogm +nlogn+m+n ),O(1)
*/
#include <algorithm>
class Solution
{
public :
    vector < int > intersect ( vector < int >& nums1 , vector < int >& nums2 )
    {
        if(nums1.empty() || nums2.empty()) return {};
 
        vector<int> res;
        int i = 0 , j = 0 ;        
        sort ( nums1 . begin (), nums1 . end ());
        sort ( nums2 . begin (), nums2 . end ());
 
        while ( i < nums1 . size () && j < nums2 . size ()) //i j 分别用来遍历两个数组
        {
            if ( nums1 [ i ] < nums2 [ j ]) i ++; // 递增第一个数组的指针
            else if ( nums1 [ i ] > nums2 [ j ]) j ++; // 递增第二个数组的指针
            else
            {
                res . push_back ( nums1 [ i ]);
                i ++; j ++; // 同时递增两个数组指针
            }
        }
        return res ;
      
    }
};
 
 

 

posted @ 2019-01-05 14:10 wikiwen 阅读( ...) 评论( ...) 编辑 收藏
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值