两数之和 两个数组的交集 两个数组的交集II C++

一、LeetCode-1. 两数之和

题目

1.两数之和

代码

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> hashMap;
        hashMap[nums[0]] = 0;
        for(int i=1; i<nums.size(); i++) {
        auto it = hashMap.find(target-nums[i]);
            if(it != hashMap.end()) {
                return {i, it->second};
            }
            hashMap[nums[i]] = i;
        }
        return {};
    }
};

思路

最简单的思路是嵌套两层for循环,然后提交代码,超时

可以利用哈希表将时间复杂度将为O(n)

对每一个 target ,我们可以分为 xtarget - x ,通过遍历nums确定 x ,再在哈希表中查找 target - x ,若存在则返回value索引,否则将 x 加入哈希表中

复杂度

时间复杂度O(n),空间复杂度O(n)

二、LeetCode-349. 两个数组的交集

题目

349.两个数组的交集

代码

//HashTable
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        vector<int> ans;
        unordered_set<int> n1(nums1.begin(), nums1.end());
        for(int i=0; i<nums2.size(); i++) {
            if(n1.empty()) {	//检查n1是否已经为空,若空则返回ans
                return ans;
            }
            if(n1.count(nums2[i])) {
                ans.push_back(nums2[i]);
                n1.erase(nums2[i]);
            }
        }
        return ans;
    }
};
//双指针
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        int p = 0, q = 0;
        int res;
        vector<int> ans;
        sort(nums1.begin(), nums1.end());
        sort(nums2.begin(), nums2.end());
        res = nums1[0] - 1;
        while(p < nums1.size() && q < nums2.size()) {
            if(nums1[p] == res) { 
                p++;
                continue;
            }
            if(nums2[q] == res) {
                q++;
                continue;
            }
            if(nums1[p] > nums2[q]) {
                q++;
            }
            else if(nums1[p] < nums2[q]) {
                p++;
            }
            else {
                ans.push_back(nums1[p++]);
                res = nums2[q++];
            }
        }
        return ans;
    }
};

思路一(哈希表)

先将其中一个数组的元素用哈希表存储

再遍历另一个数组的元素,查找哈希表 n1 中是否存在该元素,若存在则push进 ans 中,并且将该元素从 n1 中删除

n1 为空之后,中断循环直接返回ans

思路二(双指针)

先对两个数组排序,使其保证有序性

再通过 pq 同时遍历nums1和nums2

此时会出现三种情况:

  1. p 所指的值与 q 相等,则将值push进 ans 并通过 res 标记当前添加值
  2. p 的所指值与 q 不同,则谁小谁向右移动一位
  3. 若两指针所指的值与 res 相等,则当前指针向右移动一位

当某一指针遍历完某个对应数组时,结束循环返回ans

复杂度

思路一:时间复杂度O(m+n),空间复杂度O(m+n)

思路二:时间复杂度O(mlogm+nlogn),空间复杂度(logm+logn)

for (auto x : nums1)


注意代码:

for (auto x : nums1)

这里语句auto i : nums1的效果就是遍历容器nums1,一般当然是使用iteratorl来遍历,写法比这个复杂一点:

for (vector<int>::iterator it = nums.begin(); it != nums.end(); it++)
for (vector<int>::iterator it = nums.begin(); it < nums.end(); it++)

摘自https://www.cnblogs.com/PiaYie/p/14977764.html


三、LeetCode-350. 两个数组的交集 II

题目

350.两个数组的交集 II

代码

//HashTable
class Solution {
public:
    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
        vector<int> ans;
        unordered_map<int, int> n1;
        for(int num : nums1) {
            n1[num]++;
        }
        for(int num : nums2) {
            if(n1.count(num)) {
                ans.push_back(num);
                n1[num]--;
                if(n1[num] == 0) {
                    n1.erase(num);
                }
            }
        }
        return ans;
    }
};
class Solution {
public:
    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
        vector<int> ans;
        int p = 0, q = 0;
        sort(nums1.begin(), nums1.end());
        sort(nums2.begin(), nums2.end());
        while(p < nums1.size() && q < nums2.size()) {
            if(nums1[p] == nums2[q]) {
                ans.push_back(nums1[p]);
                p++;
                q++;
            } else {
                nums1[p] < nums2[q] ? p++ : q++;
            }
        }
        return ans;
    }
};

思路一(哈希表)

使用哈希表 n1 记录nums1,key为nums1元素值,value为对应值出现的次数

当nums2中有元素在 n1 中,则将该元素push进 ans中并减少其在 n1 中出现的次数,即 value-1

当value为0时,则删除该key

优化

nums1 的大小比 nums2 小,为了减小比较次数

  1. 可以交换 nums1nums2,只需在函数最开始加上

    if (nums1.size() > nums2.size()) {
    	return intersect(nums2, nums1);
    }
    
  2. 在遍历 nums2 最开始加上

    if (n1.empty()) {
        return ans;
    }
    

思路二(双指针)

这个思路与上一题思路有所简化

先对两个数组排序,使其保证有序性

再通过 pq 同时遍历nums1和nums2

此时会出现两种情况:

  1. p 所指的值与 q 相等,则将值push进 ans
  2. p 的所指值与 q 不同,则谁小谁向右移动一位

当某一指针遍历完某个对应数组时,结束循环返回ans

复杂度

思路一:时间复杂度O(m+n),空间复杂度O(n),优化后的空间复杂度O(min(m, n))

思路二:时间复杂度O(mlongm+nlogn),空间复杂度O(logm+logn)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YRoads

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值