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.(结果序列任意)

1.个人分析
(1)首先从最直观简单的方法入手,同时从头遍历两个数组,这需要两个for循环来实现,比如,数组a1的第一个元素需要与数组a2中的每个元素进行比较,直到找到相同元素或者遍历到尾部,关键是如何实现返回的数组不包含重复的元素。
(2)去重的思路有两种,一个是在遍历过程中就保证放入元素是唯一的交叉元素,另一个是在遍历完成后再对交叉元素数组进行去重操作。

2.个人解法
(1)

vector<int> intersection(vector<int>& nums1, vector<int>& nums2)
{
    vector<int>nums3;

    for (int i=0; i < nums1.size(); ++i)
    {
        for (int j=0; j < nums2.size(); ++j)
        {
            if(nums1[i] == nums2[j])
            {
                bool bExist = false;
                for(int k=0; k<nums3.size(); ++k)
                {
                    if(nums1[i] == nums3[k])
                    {
                        bExist = true;
                        break;
                    }
                }
                if(!bExist)
                {
                    nums3.push_back(nums1[i]);
                }
                break;
            }
        }
    }

    return nums3;
}

这种方法时间复杂度为O(n^3),空间复杂度为O(1),解决方法虽然直接简单,但时间复杂度让人无法容忍,在实际中肯定行不通的。

(2)

vector<int> intersection2(vector<int>& nums1, vector<int>& nums2)
{
    vector<int>nums3;

    for (int i=0; i < nums1.size(); ++i)
    {
        for (int j=0; j < nums2.size(); ++j)
        {
            if(nums1[i] == nums2[j])
            {                   
                nums3.push_back(nums1[i]);          
                break;
            }
        }
    }

    vector<int>tmp;
    if(!nums3.empty())
        tmp.push_back(nums3[0]);

    for (int i=0; i<nums3.size(); ++i)
    {
        bool bExist = false;
        for(int j=0; j<tmp.size(); ++j)
        {
            if(nums3[i] == tmp[j])
            {
                bExist = true;
                break;
            }
        }
        if(!bExist)
            tmp.push_back(nums3[i]);
    }

    return tmp;
}

该方法的时间复杂度为O(n^2),空间复杂度为O(n),相对第一种方法是用空间换时间,但这种方法依然不会是最优解法,到底用什么方法能够将时间和空间的效率进一步提升呢?

可以尝试将两个数组先进行排序,然后使用二分查找来确定交叉元素,最后将找到的交叉元素散列到哈希表中,利用哈希函数能够判断哈希表中的元素是否重复。

(3)

vector<int> intersection3(vector<int>& nums1, vector<int>& nums2)
{
    vector<int>nums3;
    nums3.resize(3 + 2*min(nums1.size(), nums2.size()));
    nums3.assign(nums3.size(), 9999);
    int key;

    //先排序
    sort(nums1.begin(), nums1.end());
    sort(nums2.begin(), nums2.end());

    //二分查找交叉元素并将其散列到哈希表中
    for (int i=0; i<nums1.size(); ++i)
    {
        if(binary_search(nums2.begin(), nums2.end(), nums1[i]))
        {
            int offset = 1;
            key = nums1[i] % nums3.size();

            while(nums3[key] != 9999 && nums1[i] != nums3[key])
            {
                key += offset;
                offset += 2;
                if(key >= nums3.size())
                    key -= nums3.size();
            }

            nums3[key] = nums1[i];                  
        }
    }

    //将交叉元素复制到另外一个数组中并返回
    vector<int>ret;
    for (int i=0; i<nums3.size(); ++i)
    {
        if(nums3[i] != 9999)
            ret.push_back(nums3[i]);
    }

    return ret;
}

该方法的时间复杂度O(nlogn),空间复杂度为O(n)。

3.总结
三种方法花了自己两天时间才实现,真心不容易,而且每个算法整体上都比较复杂,只能说还没能力想出那种既简洁又高效的解法,能实现这些不太好看的算法已属不易,继续努力吧。

PS:

  • 题目的中文翻译是本人所作,如有偏差敬请指正。
  • 其中的“个人分析”和“个人解法”均是本人最初的想法和做法,不一定是对的,只是作为一个对照和记录。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值