Leetcode刷题 由浅入深之哈希法——349. 两个数组的交集

目录

(一)数组交集的C++实现

写法一(哈希暴力搜索)

写法二(哈希集合搜索)

(二)复杂度分析

时间复杂度

空间复杂度

(三)总结


【题目链接】349.两个数组的交集 - 力扣(LeetCode)

给定两个数组 nums1 和 nums2 ,返回 它们的 交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

示例 1:

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

示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

提示:

  • 1 <= nums1.length, nums2.length <= 1000

  • 0 <= nums1[i], nums2[i] <= 1000

(一)数组交集的C++实现

哈希表:对元素的值进行哈希映射(哈希函数),映射到对应下标位置。也就是已知一个值,经过哈希函数可以直接计算在哈希表中的存储位置。

        哈希表的特点:下标可以直接访问元素。

        哈希表的作用:使用哈希表可以快速(直接根据值和哈希函数计算下标并访问)判断元素是否在表里

写法一(哈希暴力搜索)

解题思路:

        双重遍历实现比较,并将交集结果存入set类型的哈希表中。返回时,需要将哈希表转化为整型数组。

(借助哈希法就不需要再考虑重复插入的问题:set类型的哈希表数值不可以重复出现)

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        set<int> hashlist;    //哈希表的定义
        for(auto i : nums1){
            for(auto j : nums2){
                if(i == j)
                    hashlist.insert(i);    //哈希表的插入操作
            }
        }
        return vector<int> (hashlist.begin(), hashlist.end());    //返回整个哈希表构成的数组
    }
};

写法二(哈希集合搜索)

解题思路:

        借助数学中寻找集合交集的思想,可以先将一个数组nums1变成具有集合特点的数组存储(也就是存储在一个哈希表中)。接着,可以遍历另一个数组nums2,如果元素在哈希表中,则将该值添加到交集数组中并在哈希表中删除;如果不在,则不需要进行任何操作。

        这种办法时间复杂度更低,不需要遍历完两个数组的所有元素。

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        set<int> hashlist;    //定义整形哈希表
        vector<int> result;    //定义整形数组(存储交集结果)
        for(auto i : nums1)
            hashlist.insert(i);
        for(auto j : nums2)
            if(hashlist.find(j) != hashlist.end()){    //不为hashlist.end()说明哈希表hashlist中有j这个值
                result.push_back(j);    //写进数组
                hashlist.erase(j);    //删除哈希表中的j这个值
            }
        return result;
    }
};

(二)复杂度分析

时间复杂度

(1)写法一:两层嵌套循环,假设nums1的长度为mnums2的长度为n,那么比较的次数为m * nset的插入操作平均时间复杂度是O(logk),其中kset中元素的数量。在最坏情况下,插入操作的总时间复杂度为O(mnlog(mn)) 。因此,总的时间复杂度为O(mnlog(mn))

(2)写法二:第一个循环插入操作平均时间复杂度是O(logm),插入m个元素的总时间复杂度为O(mlogm)。第二个循环遍历nums2,对于nums2中的每个元素,执行查找操作和可能的删除操作,查找和删除操作的平均时间复杂度都是O(logm),因此第二个循环的总时间复杂度为O(nlogm)。所以,总的时间复杂度为O(mlogm+nlogm)

空间复杂度

(1)写法一:set用来存储交集元素,在最坏情况下,交集元素的数量可能达到min(m, n),因此set所占用的空间为O(min(m,n));返回的vector也需要O(min(m,n))。所以,总的空间复杂度为O(min(m,n))

(2)写法二:set用来存储nums1中的元素,在最坏情况下,需要O(m)的空间。result数组用来存储交集元素,在最坏情况下,交集元素的数量可能达到min(m, n),因此result数组需要O(min(m,n))的空间。所以,总的空间复杂度为O(m)

(三)总结

(1)哈希表可以快速判断元素是否在表里,相比于遍历搜索时间复杂度会更低。

(2)解题时多找一下数学规律。

(3)哈希法解决问题一般有三种:数组,集合,映射。(数组见博客Leetcode刷题 由浅入深之哈希表——242. 有效的字母异位词-CSDN博客

这道题目采用的是集合的第一种,set类型的数据结构

        定义:set<int> name;        i为整形的元素。

        查找:name.find(i);        name.find(i) != name.end()表示可以找到。

        插入:name.insert(i);

        删除:name.erase(i);

        set类型哈希法特性:底层实现是红黑树,是有序的,无重复元素,不能更改数值,可以增删查(效率为O(log n))。

学习中,诚挚希望有心者指正和交流,经验或者方法都可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值