Day 5 | LeetCode 刷题

本文详细分析了如何使用哈希表解决242个有效字母异位词的问题,以及349个数组交集的高效算法,涉及unordered_set和set的比较,同时介绍了202快乐数和1两数之和的解决方案,强调了时间和空间复杂度优化。
摘要由CSDN通过智能技术生成

题目:242 有效的字母异位词、349 两个数组的交集、202 快乐数、1 两数之和
打卡日期:20204.2.1、2.4

242 有效的字母异位词

数组就是简单的哈希表
当使用哈希表解决问题时,常使用以下三种数据结构:

  • 数组
  • set(集合)
  • map(映射)
class Solution {
public:
    bool isAnagram(string s, string t) {
        int record[26] = {0};
        bool flag = true;
        for (int i=0; i<s.size(); i++) {
            record[s[i] - 'a']++;
        }
        for (int i=0; i<t.size(); i++) {
            record[t[i] - 'a']--;
        }
        for (int i=0; i<26; i++) {
            if (record[i] != 0) {
                flag = false;
                break;
            }
        }
        return flag;
    }
};

时间复杂度:O(n)
空间复杂度:O(1)

349 两个数组的交集

在这里插入图片描述

数组

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result_set;  // 存放结果
        int hash[1000] = {0};
        for (int num : nums1) {
            hash[num] = 1;
        }
        for (int num : nums2) {
            if (hash[num] == 1) {
                result_set.insert(num);
            }
        }
        vector<int> result(result_set.begin(), result_set.end());
        return result;
    }
};

时间复杂度: O(m + n),m是最后要把set转成vector
空间复杂度: O(n)

集合(set)

如果哈希值较少、特别分散、跨度较大,使用数组将造成空间的浪费
可以考虑另一种结构体:set 集合,集合里的元素保持唯一性(已去重):

  • std::set
  • std::multiset
  • std::unordered_set

set 和 multiset 的底层实现都是红黑树,unordered_set 底层实现是哈希表,使用 unordered_set 效率是最高的,不需要对数据进行排序
———————————————————————————————————
那么遇到哈希问题可以都用set吗?

  • No!
    直接使用set 不仅占用空间比数组大,而且速度要比数组慢,set把数值映射到key上都要做hash计算的。不要小瞧这个耗时,在数据量大的情况,差距是很明显的。
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result_set;  //存放结果
        unordered_set<int> nums_set(nums1.begin(), nums1.end());
        // 检验nums2的数字是否在nums1的集合中出现过
        for (int num : nums2) {
            if (nums_set.find(num) != nums_set.end()) { // 若出现过
                result_set.insert(num);
            }
        }
        vector<int> result(result_set.begin(), result_set.end());   // 转化为vector结构返回
        return result;
    }
};

nums_set.find(num) 是调用集合(set)的 find 方法,该方法返回一个指向包含元素 num 的位置的迭代器。如果 num 存在于集合中,迭代器指向该元素的位置;如果不存在,则返回集合的末尾(end)。

时间复杂度:O(n+m),m是最后要把set转成vector
空间复杂度:O(n)

202 快乐数

思路:
题目中说会无限循环,即在求和的过程中,sum会重复出现。正如我们所知,当我们遇到要快速判断一个元素是否出现在集合中时,就要考虑哈希法
因此,这道题使用哈希法来判断sum是否重复出现(unordered_set),若是则return false,否则直至sum为1.

class Solution {
public:
    int getSum(int n) {
        int sum = 0;
        while (n) {
            sum += (n%10) * (n%10);
            n = n / 10;
        }
        return sum;
    }

    bool isHappy(int n) {
        unordered_set<int> set;
        bool flag = false;
        while (1) {
            int sum = getSum(n);
            if (sum == 1) {
                flag = true;
                break;
            }
            if (set.find(sum) != set.end()) {   // 在集合中,已经存在
                break;
            } else {
                set.insert(sum);  
            }
            n = sum;
        }
        return flag;
    }
};

时间复杂度: O(logn)
空间复杂度: O(logn)

1 两数之和

注:题目要求是两个数,因此两下标不能一样

暴力解法

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        for (int i=0; i<nums.size(); i++) {
            for (int j=i+1; j<nums.size(); j++) {
                if (nums[i] + nums[j] == target) {
                    return {i, j};
                }
            }
        }
        return {};
    }
};

时间复杂度:O(n^2)
空间复杂度:O(1)

哈希表

该题的思路就是枚举数组中的每一个x,寻找数组中是否存在target-x,问题的关键就在于如何寻找target-x
暴力解法中是使用for循环迭代查找,时间复杂度为O(n),使用哈希表来确定数组中是否存在目标元素则可以将复杂度降为O(1)。这样,我们创建一个哈希表,对于每一个x,查询表中是否存在target-x,然后将x插入表中,这样可以保证x不会和自己匹配。

由于本题,我们不仅需要知道元素是否遍历过,还要知道元素对应的下标,因此使用key-value结构来存放,key存元素,value存下标,使用map结构正合适。
在这里插入图片描述

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map <int, int> map;
        for (int i=0; i<nums.size(); i++) {
            // 遍历当前元素,并在map中寻找是否有匹配的key
            auto iter = map.find(target-nums[i]);
            if (iter != map.end()) {    // 哈希表中存在
                return {iter->second, i};
            }
            // 如果没找到匹配对,就把访问过的元素和下标加入到map中
            map.insert(pair<int, int>(nums[i], i));
        }
        return {};
    }
};

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值