Day05:242.有效的字母异位词、349. 两个数组的交集、202. 快乐数、1. 两数之和

本文介绍了如何使用哈希表和unordered_set/unordered_map解决字符串异位词、数组交集、快乐数和两数之和等问题,展示了它们在算法中的高效应用以及注意事项。
摘要由CSDN通过智能技术生成

242.有效的字母异位词


题目链接

思路

这个题目其实很简单,用普通的哈希表就可以解决,把连续字符的出现放在连续的数组里,用下标分别表示不同的字符,重点是理解这种方法,过程我就不赘述啦。

代码实现

class Solution {
public:
    bool isAnagram(string s, string t) {
        int hash[26]={0};
        for(int i=0;i<s.size();i++){
            hash[s[i]-'a']++;
        }
        for(int i=0;i<t.size();i++){
            hash[t[i]-'a']--;
        }
        for(int i=0;i<26;i++){
            if(hash[i]!=0)return false;
        }
        return true;
    }
};

总结

一般哈希表都是用来快速判断一个元素是否出现集合里,就用哈希表。暴力法可以解决但是时间复杂度一般是成倍数增长。


349. 两个数组的交集


题目链接

思路

我的第一反应还是使用数组,但是这样会有一个问题,就是无法确定数组的空间到底需要多少,看了卡哥的讲解我才知道原来神奇的STL里还有unordered_set这样的好东西。
它的底层逻辑还是一个哈希表,只不过是一个无序哈希表。使用unordered_set 读写效率是最高的,并不需要对数据进行排序,而且还不要让数据重复,用find( )、insert( )、end( ),操作快捷又避免元素重复。

代码实现

1.unordered_set实现

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result_set; // 存放结果,之所以用set是为了给结果集去重
        unordered_set<int> nums_set(nums1.begin(), nums1.end());
        for (int num : nums2) {
            // 发现nums2的元素 在nums_set里又出现过
            if (nums_set.find(num) != nums_set.end()) {
                result_set.insert(num);
            }
        }
        return vector<int>(result_set.begin(), result_set.end());
    }
};
  1. unordered_map实现
class Solution {
public:
    vector<int> intersection(vector<int>& s, vector<int>& t) {
        unordered_map<int,int> hash;
        vector<int> result;
        for(int i=0;i<s.size();i++){
            hash[s[i]]++;
        }
        for(int i=0;i<t.size();i++){
            if(hash.find(t[i])!=hash.end()&&hash[t[i]]!=0){
                result.push_back(t[i]);
                hash[t[i]]=0;
            }
        }
        return result;
    }
};

总结

用unordered_set输出结果中的每个元素一定是唯一的,也就是说输出的结果的去重的, 数据大小不确定的,同时可以不考虑输出结果的顺序时可以用unordered_set。set初始化的方法也要记得。
注:return的数据是vector的,要经过一个转化过程:
vector(result_set.begin(), result_set.end())

用unordered_map也挺方便的,num1里面的元素记录hash表内,如果表内存在num2内的元素放入result结果集就好了。


202. 快乐数


题目链接

思路

看见这个题目我其实是没什么思路的(脑袋比较不灵活😢)。然后学习到了一个新的方法,就是发现得到的sum值重复时就证明进入了循环(妙啊!)。所以这道题的思路就是把把sum存起来,然后发现新得到的sum和set里面的某个数据一样就可以return false啦。

代码实现

class Solution {
public:
    bool isHappy(int n) {
        unordered_set<int> hash;
        while(n){
            if(n==1)return true;
            int tmp=n;
            int sum=0;
            while(tmp){
                sum+=(tmp%10)*(tmp%10);
                tmp/=10;
                n=sum;
            }
            if(hash.find(n)!=hash.end())return false;
            else hash.insert(n);
        }
        return 0;
    }
};

总结

确实挺不错的哈哈哈。不多说,和上一道题差不多。


1. 两数之和


题目链接

思路

再强调一下 什么时候使用哈希法:当我们需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要第一时间想到哈希法。
这道题就是判断两元素什么时候之和会满足条件,显而易见又是哈希。我们不仅要知道元素有没有遍历过,还要知道这个元素对应的下标,需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适

为什么不用数组或set呢?

  • 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
  • set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set也不能用。

代码实现

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        std::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)

总结

一刷:学到了些新的东西:

  • unordered_map并不需要key有序,选择unordered_map 效率更高
  • 当需要查找且返回一些数据时用map
  • map.insert(pair<int,int>(key,value)),insert的元素不要弄错了哦
  • return空vector时需要用{ }

二刷:第一反应是采用排序后双指针的方法了,但是忽略了相同元素的情况,所以还是一刷学的方法更好,还是需要重复记忆啊哈哈哈。


小记

一刷:今天有点忙,但是明天只会更忙,但更忙也要坚持,加油加油加油!😆😆😆
二刷:最近有点懈怠了,没跟上大部队,加油补上。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值