代码随想录Day10-哈希表:力扣349、350、202题

349. 两个数组的交集

题目链接
代码随想录文章讲解链接

方法一:哈希表

思路

用一个哈希表存储第一个数组出现的元素,然后遍历第二个数组查看是否在第一个数组里出现过,注意的点是返回的数组的元素是唯一的,所以要注意判断是否是唯一的。由于题目说明了数组的元素的取值介于0到1000,所以也可以使用数组来代替哈希表记录。

  • 时间复杂度: O ( n + m ) O(n+m) O(n+m)
  • 空间复杂度: O ( c ) O(c) O(c)
C++代码
// 使用哈希表记录
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_map<int, int> hashMap;
        vector<int> res;

        for (int& n1 : nums1) ++hashMap[n1];
        for (int& n2 : nums2) {
            if (hashMap.find(n2) != hashMap.end() && hashMap[n2] > 0) {
                res.push_back(n2);
                hashMap[n2] *= -1;
            }
        }
        return res;
    }
};

// 使用数组记录
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        int record[1001] = {0};
        vector<int> res;

        for (int& n1 : nums1) record[n1] = 1;
        for (int& n2 : nums2) {
            if (record[n2] == 1) {
                res.push_back(n2);
                --record[n2];
            }
        }
        return res;
    }
};

方法二:排序+遍历

思路

先把两个数组进行排序,然后再同时遍历两个数组。

  • 时间复杂度: O ( n log ⁡ n + m log ⁡ m ) O(n\log{n} + m\log{m}) O(nlogn+mlogm)
  • 空间复杂度: O ( log ⁡ n + log ⁡ m ) O(\log{n} + \log{m}) O(logn+logm)
C++代码
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        int idx1 = 0;
        int idx2 = 0;
        int size1 = nums1.size();
        int size2 = nums2.size();
        vector<int> res;

        sort(nums1.begin(), nums1.end());
        sort(nums2.begin(), nums2.end());
        while (idx1 < size1 && idx2 < size2) {
            if (nums1[idx1] == nums2[idx2]) {
                if (res.size() == 0 || res.back() != nums1[idx1]) res.push_back(nums1[idx1]);
                ++idx1;
                ++idx2;
            } else if (nums1[idx1] < nums2[idx2]) ++idx1;
            else ++idx2;
        }
        return res;
    }
};

看完讲解的思考

无。

代码实现遇到的问题

无。


350. 两个数组的交集 II

题目链接

方法一:哈希表

用时:3m5s

思路

与上一题差不多。

  • 时间复杂度: O ( m + n ) O(m+n) O(m+n)
  • 空间复杂度: O ( c ) O(c) O(c)
C++代码
class Solution {
public:
    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
        unordered_map<int, int> hashMap;
        vector<int> res;

        for (int& n1 : nums1) ++hashMap[n1];
        for (int& n2 : nums2) {
            if (hashMap.find(n2) != hashMap.end() && hashMap[n2] > 0) {
                res.push_back(n2);
                --hashMap[n2];
            }
        }
        return res;
    }
};

方法二:排序+遍历

用时:3m8s

思路

与上一题类似。

  • 时间复杂度: O ( m log ⁡ m + n log ⁡ n ) O(m\log{m}+n\log{n}) O(mlogm+nlogn)
  • 空间复杂度: O ( log ⁡ m + log ⁡ n ) O(\log{m} + \log{n}) O(logm+logn)
C++代码
class Solution {
public:
    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
        int idx1 = 0;
        int idx2 = 0;
        int size1 = nums1.size();
        int size2 = nums2.size();
        vector<int> res;

        sort(nums1.begin(), nums1.end());
        sort(nums2.begin(), nums2.end());
        while (idx1 < size1 && idx2 < size2) {
            if (nums1[idx1] == nums2[idx2]) {
                res.push_back(nums1[idx1++]);
                ++idx2;
            } else if (nums1[idx1] < nums2[idx2]) ++idx1;
            else ++idx2;
        }
        return res;
    }
};

看完讲解的思考

无。

代码实现遇到的问题

无。


202. 快乐数

题目链接
代码随想录文章讲解链接

方法一:哈希表

用时:13m30s

思路

如果n不是快乐数,那么n在变换的过程中一定会出现重复的数字,故使用哈希表记录出现过的数字,当重复时则返回false。

  • 时间复杂度: O ( log ⁡ n ) O(\log{n}) O(logn),此处的log是以10为底的,主要是计算每个位数的值的时间复杂度。
  • 空间复杂度: O ( log ⁡ n ) O(\log{n}) O(logn)。具体推导见题解。
C++代码
class Solution {
public:
    bool isHappy(int n) {
        unordered_set<int> hashSet;
        int sum;
        while (true) {
            hashSet.insert(n);
            sum = getSum(n);
            if (sum == 1) return true;
            else if (hashSet.find(sum) != hashSet.end()) return false;
            n = sum;
        }
    }
    int getSum(int n) {
        int sum = 0;
        while (n) {
            sum += (n % 10) * (n % 10);
            n /= 10;
        }
        return sum;
    }
};

方法二:快慢数

思路

判断是否有循环,类似于判断链表是否有环,可以使用两个数字,一个数字每次更新一步,一个数字每次更新两步,若存在循环,则两个数字一定会相遇。

  • 时间复杂度: O ( log ⁡ n ) O(\log{n}) O(logn)
  • 空间复杂度: O ( 1 ) O(1) O(1)
C++代码
class Solution {
public:
    bool isHappy(int n) {
        int slow = n;
        int fast = n;
        while (true) {
            slow = getSum(slow);
            fast = getSum(getSum(fast));
            if (slow == 1) return true;
            if (slow == fast) return false;
        }
    }
    int getSum(int n) {
        int sum = 0;
        while (n) {
            sum += (n % 10) * (n % 10);
            n /= 10;
        }
        return sum;
    }
};

看完讲解的思考

为什么循环过程数字一定不会无限变大,而是会变成1或者循环?
当每个位数都取最大值9时的变换:9 => 81,99 => 162,999 => 243,…
观察可知,即使都取最大值9,当位数大于等于2时,数字变换是会变小的,所以不可能无限增大。所以一定会循环。

代码实现遇到的问题

不知道如何获取一个数字的每个位数上的值,一开始用的方法是转换成字符串,再获取到每个字符,再转换成数字,过于麻烦,实际上可以通过循环求余得到。


最后的碎碎念

这几天一直在忙论文的rebuttal,时间紧任务重,就没时间刷题了,停了几天。现在rebuttal搞完了,继续刷,10天没刷,还好手感还在。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值