代码随想录算法训练营第6天 | 哈希表理论基础, 242.有效字母异位词 anagram, 349. 两数组交集, 202. 快乐数, 1.两数之和

哈希知识一些记录:

  • 虽然std::set、std::multiset 的底层实现是红黑树,不是哈希表,std::set、std::multiset 使用红黑树来索引和存储,不过给我们的使用方式,还是哈希法的使用方式,即key和value。所以使用这些数据结构来解决映射问题的方法,我们依然称之为哈希法。 map也是一样的道理。
  • 哈希法也是牺牲了空间换时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。
  • 做面试题目时遇到需判断一个元素是否出现过的场景也应该第一时间想到哈希法

#242 anagram multiset和unordered_map都试了下,看代码随想录答案用的array,容易的快题,

注意:

1 erase(key)not value

2 map[char]+=1; 如果一开始不存在,会自动创一个,并使用该类型的默认值进行初始化,比如0

3 string 不用管 \0,遍历可用 传统i++, itr++, auto ele:str

bool isAnagram(string s, string t) {
        //multiset (repeated letter, no cnt)
        multiset<char> setT;
        for( int i =0; i<t.size();i++){
            setT.insert(t[i]);
        }
        
        for( int i =0; i<s.size();i++){
            if (setT.find(s[i]) != setT.end()){
                setT.erase(setT.find(s[i]));
            }
            else{
                return false;

            }
        }
        

        return setT.empty();
bool isAnagram(string s, string t) {
        //unordered_map (letter: cnt)
        unordered_map<char, int> mapt;
        for( int i =0; i<t.size();i++){
            mapt[t[i]] += 1;
        }

        for (unordered_map<char, int>::iterator it = mapt.begin(); it != mapt.end(); ++it) {
            cout << "Key: " << it->first << " Value: " << it->second << endl;
        }
        for( int i =0; i<s.size();i++){
            if (mapt.find(s[i]) != mapt.end()){
                mapt[s[i]] -= 1;
                if(mapt[s[i]]==0){
                    mapt.erase(s[i]);
                }
            }
            else{
                return false;
            }
        }

        return mapt.empty();

    }

#349 intersection of array

这是标准思路,找到了直接push back vec

vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        set<int> set1;
        set<int> set2;
        for (int i=0; i<nums1.size();i++){
            set1.insert(nums1[i]);
        }
        for (int i=0; i<nums2.size();i++){
            set2.insert(nums2[i]);
        }
        vector<int> res;

        for(set<int>::iterator it=set1.begin();it!=set1.end();it++){
                if(set2.find(*it)!=set2.end()){
                res.push_back(*it);
            }
        }
        return res;
    }
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        set<int> set1;
        set<int> set2;
        for (int i=0; i<nums1.size();i++){
            set1.insert(nums1[i]);
        }
        for (int i=0; i<nums2.size();i++){
            set2.insert(nums2[i]);
        }
        vector<int> res;
        
        for (auto it = set1.begin(); it != set1.end(); ) {
        if (set2.find(*it) == set2.end()) {
            it = set1.erase(it);  // 删除元素,并更新迭代器
        } else {
            ++it;  // 移动到下一个位置
        }
    }

    for (auto it = set1.begin(); it != set1.end(); it++) {
        res.push_back(*it);
    }
        return res;
        
    }

上面这是我一开始的思路:找到了不是的从nums1里删掉,最后num1统一转vec

关键易错点是 不能边itr 边 erase(itr),要做处理,因为erase了不用++了,它相当于自动++了

#202 快乐数

bool isHappy(int n) {
        //brute force
        //multiset
        set<int> nset;
        multiset<int> myset;
        nset.insert(n);

        while(1){
            myset.clear();
            while(n/10!=0){
                int digit=n-(n/10)*10;
                n/=10;
                myset.insert(digit); 
            }
            myset.insert(n);
        
            n=0;
            for(const auto& ele : myset) {
                n+=ele*ele;
            }
            
            if(n==1){
                return true;
            }

            if(nset.find(n)==nset.end()){
                nset.insert(n);
            }
            else{
                return false;
            }
        }

        return false;
        
    }

这题自己写的,不难,但时间复杂度不会分析,问了gpt也没看懂。代码随想录的答案好像跟我差不多,没仔细看,时间复杂度again不会分析

#1 两数之和 经典
折腾半天得有1小时,其实自己思路快对了,看了答案思路略微修改

我已经想到 1 必须用map 因为要index 2 pair(nums[i],i)是和正常相反的

vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> mymap;
        vector<int> res;

        for (int i=0; i<nums.size(); i++){
            auto it = mymap.find(target-nums[i]);
            
            if(it != mymap.end()) {
                res.push_back(it->second);
                res.push_back(i);
                break;
            }
            else{
                mymap.insert(make_pair(nums[i],i));
            }
            
        }
        return res;
    }

没想到的点是不要一次放完,要边放边找,解决(3,3)那种case

今天其他学到的:

1.标答里两句要学:set和vec的互相转化,直接用begin end itr
unordered_set<int> nums_set(nums1.begin(), nums1.end());
return vector<int>(result_set.begin(), result_set.end());

2.set find(*it), erase(it) 
map find(key) ,erase(key)

3 auto &, &代表是not copy,就是原来那个

然后多用c++11特性,比如 auto和 range for

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值