day6-代码随想录算法训练营(19)-哈希表1 已二刷

242.有效得字母异位词

思路一:两个哈希表直接比较
class Solution {
public:
    bool isAnagram(string s, string t) {
        unordered_map<char,int>ans1,ans2;
        if(s.size()!=t.size())
            return false;
        for(int i=0;i<s.size();i++)
        {
            ans1[s[i]]++;
        }
        for(int i=0;i<t.size();i++)
        {
            ans2[t[i]]++;
        }
        return ans1==ans2;
    }
};

看了题解想起来直接用哈希解法更快更牛逼

思路二:直接用字母的ASCII值的相对排序来表示下标,然后同时对s和t遍历,异位的话数组最终必然都为0

易错点:数组记得初始化为0吧 

class Solution {
public:
    bool isAnagram(string s, string t) {
        if(s.size()!=t.size())
            return false;
        int ans[26]={0};
        for(int i=0;i<s.size();i++)
        {
            ans[s[i]-'a']++;
            ans[t[i]-'a']--;
        }
        for(int i=0;i<26;i++)
        {
            if(ans[i]!=0)
                return false;
        }
        
        return true;
    }
};
二刷:
 思路三:string内部也可以进行排序,直接排序判断是否相等
class Solution {
public:
    bool isAnagram(string s, string t) {
        if(s.size()!=t.size()) return false;
        sort(s.begin(),s.end());
        sort(t.begin(),t.end());
        return s==t;
    }
};
思路二:哈希特性
class Solution {
public:
    bool isAnagram(string s, string t) {
        if(s.size()!=t.size()) return false;
        vector<int>cmp(26,0);
        for(int i=0;i<s.size();i++){
            int indexs=s[i]-'a';
            int indext=t[i]-'a';
            cmp[indexs]++;
            cmp[indext]--;
        }
        return count(cmp.begin(),cmp.end(),0)==cmp.size();
    }
};

349.两个数组的交集

思路:就是遍历两次,使用unordered_set便于快速查找,第一次把nums1的元素插入set,第二次检查nums2的元素在set中就直接插入result(同时进行去重)

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        vector<int>result;
        unordered_set<int>ans;
        for(int i=0;i<nums1.size();i++)
        {
            ans.emplace(nums1[i]);
        }
        for(auto it:nums2)
        {
            if(ans.find(it)!=ans.end() && find(result.begin(),result.end(),it)==result.end())
                result.push_back(it);
        }
        return result;
    }
};
 二刷:
思路一:unordered_map记录,unordered_map查找
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        vector<int>res;
        unordered_map<int,int>map;
        for(auto it:nums1) map[it]++;
        for(auto it:nums2){
            if(map[it]>0){
                res.push_back(it);
                map[it]=0;
            }
        }
        return res;
    }
};

思路二: unordered_set
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        vector<int>res;
        unordered_set<int>set;
        for(auto it:nums1){
            if(set.find(it)==set.end()) set.insert(it);
        }
        for(auto it:nums2){
            if(set.find(it)!=set.end()){
                res.push_back(it);
                set.erase(it);
            }
        }
        return res;
    }
};

202.快乐数

分析:这一题想了一会儿不知道咋用哈希表,对于每一位的平方自然是个位开始,先%10找出个位,再/10去掉个位;但是如何确定永远不会变为1呢???看了题解之后自己写了一遍

思路一:

还是使用unordered_set,对n进行每一位平方和之后,寻找set中是否存在,不存在也不等于1就把结果赋给n,继续下一次平方和;

平方和等于1时直接放回true;

当平方和第二次出现在set中时说明已经陷入循环!!!这个思路没看题解完全没想出来,感觉还是逻辑思维能力差了点,分析的不够精确,慢慢练

class Solution {
public:
    //获取各个位上得单数之和
    int getSum(int n)
    {
        int sum=0;
        while(n)
        {
            sum+=(n%10)*(n%10);//获取个位
            n/=10;//删除个位
        }
        return sum;
    }
    bool isHappy(int n) {
        unordered_set<int>set;
        while(1)
        {
            int sum=getSum(n);
            if(sum==1)
            {
                return true;
            }
            //如果这个sum曾经出现过,说明已经陷入死循环,马上停止
            if(set.find(sum)!=set.end()){
                return false;
            }else{
                set.insert(sum);
            }
            n=sum;
        }
    }
};
 二刷:
思路一:
  • 当结果重复出现的时候,说明无法变化为1,即返回false,
  • 使用lambda函数进行快乐变化
  • 使用unordered_set进行重复查询

注意:lambda表达式的类型尽量使用auto,否则容易报错

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

 

1.两数之和

分析:这一题刚开始想的比较复杂,然后看了题解发现只需要一次遍历就能解决;

首先题目要求只需要直到一对元素就行,其次等于target,故此只需要边遍历边寻找target-当前值就行,找不到就把当前值加入set。思路感觉挺简单,但自己做的时候脑袋感觉转不过来弯,看来是平时题解没有认真分析研究。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        //思路:遍历一边数组,使用哈希表记录顺序,再遍历一遍数组,
        //记录target-当前数,在哈希表中查找,并且值与当前数得值不相等,查找后直接赋值为-1
        unordered_map<int,int>ans;
        for(int i=0;i<nums.size();i++)
        {
            auto it=ans.find(target-nums[i]);
            if(it!=ans.end())
            {
                return {it->second,i};
            }
            //如果没找到,就把当前值插入哈希表
            ans[nums[i]]=i;
        }
        return {};

    }
};
二刷:简单题重拳出击 
思路:unordered_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++){
            int mid=target-nums[i];
            if(map[mid]>0) return {i,map[mid]-1};
            map[nums[i]]=i+1;
        }
        return {};
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值