代码随想录算法训练营第六天 | LeetCode 242、349、202、1


前言

LeetCode题目:LeetCode 242、349、202、1
Takeaway:哈希表知识;STL容器:set 和 map的使用方法;不同容器的不同版本以及其底层逻辑。


一、LeetCode 242

这题是用数组来实现哈希表,选择数组的原因是哈希表内元素很少,顺便也考验一点点对ASCII码的理解。

class Solution {
public:
    bool isAnagram(string s, string t) {
        int hash_nums[26] = {0};

        if(s.size() != t.size()){
            return false;
        }

        for(int i=0; i<s.size(); i++){
            hash_nums[s[i]-'a']++;
            // cout<<s[i]<<":"<<hash_nums[s[i]-'a']<<endl;
        }

        // cout<<"_______"<<endl;

        for(int i=0; i<t.size(); i++){
            hash_nums[t[i]-'a']--;
            // cout<<t[i]<<":"<<hash_nums[t[i]-'a']<<endl;
        }

        int flag = 1;
        for(int i=0; i<26; i++){
            if(hash_nums[i] != 0){
                flag = 0;
                break;
            }
        }

        if(flag == 1){
            return true;
        }
        return false;
    }
};

二、LeetCode 349

本题就需要使用set来实现哈希表了,unordered_set不含重复元素满足题目要求,并且速度比普通set快。所以选用它。这题也学到了set的用法和vector与set的转换方法。

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> set1;
        for(int i=0; i<nums1.size(); i++){
            set1.insert(nums1[i]);
        }

        unordered_set<int> set2;
        for(int i=0; i<nums2.size(); i++){
            if(set1.find(nums2[i]) != set1.end()){
                set2.insert(nums2[i]);
            }
        }

        return vector<int>(set2.begin(), set2.end());
    }
};

三、LeetCode 202

本题也是使用set来实现哈希表的一道题,如果出现无限循环,那么说明当前的n之前一定已经出现过了,所以我们就可以用哈希表来快速检查这个数是否出现过。此题难度可能在复杂的模拟过程中,但是我做过很多类似的模拟题,所以整体没什么难度。

class Solution {
public:
    bool isHappy(int n) {
        unordered_set<int> existNum;
        while(n != 1){
            /* 找到重复元素了 */
            if(existNum.find(n) != existNum.end()){
                return false;
            }

            existNum.insert(n);

            vector<int> eachNum;
            int num;
            while(n>0){
                num = n%10;
                n = n/10;
                eachNum.push_back(num*num);
            }
            for(int i=0; i<eachNum.size(); i++){
                n += eachNum[i];
            }
           
        }
        return true;
    }
};

四、LeetCode 1

1、排序+双指针解法

这个解法是我在没看参考文章前自己写的,并没有使用到map容器,并且算法复杂度石O(nlogn),要优于参考文章复杂度为O(n^2)的算法,但是考虑到本题的目的是训练我们如何使用map容器,所以我又再写了一个使用map的解法。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size()-1;

        int num1, num2;

        //sort会改变原数组,得留个备份
        vector<int> nums_orginal = nums;

        //排序后才能用双指针操作
        sort(nums.begin(), nums.end());
        vector<int> ans;

        //left == right就到头了
        while(left != right){
            int cur = nums[left]+nums[right];
            if(cur == target){
                num1 = nums[left];
                num2 = nums[right];
                break;
            }else if(cur > target){
                right--;
            }else{
                left++;
            }
        }

        //找两个数在原数组的位置,这就是为什么原数组要存个备份
        for(int i = 0; i<nums_orginal.size(); i++){
            if(nums_orginal[i] == num1){
                ans.push_back(i);

                // 防止出现[3,3]这种俩数字一样的情况
                nums_orginal[i] = -1;
                break;
            }
        }

        for(int i = 0; i<nums_orginal.size(); i++){
            if(nums_orginal[i] == num2){
                ans.push_back(i);
                break;
            }
        }

        return ans;
    }
};

2、使用map实现

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> map;
        vector<int> ans;
        for(int i=0; i<nums.size(); i++){
        	// 在map中寻找值为target-nums[i]的元素,满足条件就说明找到了
            if(map.find(target-nums[i])!=map.end()){
            	// ans里存储的是位置
                ans.push_back(i);
                ans.push_back(map[target-nums[i]]);
            }
            map.insert(pair<int, int>(nums[i],i));
        }
        return ans;
    }
};

总结

今天题目都是要靠哈希表来解决的,哈希表的实现方法主要有数组,set 和 map 这三种,每种都有不同的使用场景:
当哈希表内元素很少的时候,使用数组会方便一些;
当哈希表内元素很多的时候(或者是未知大小,此时你无法定义数组),使用 set 会更好一些;
当哈希表需要键值对的时候,比如 Leetcode 1 这道题,需要同时保存元素的值和位置,这就是一个键值对,此时使用 map 是更好的解法。

此外,对于 set 和 map,每个都有标准版,multi版和unorder版,具体使用哪个要根据实际需求来,其中标准版和multi版都是使用红黑树来实现的,其特点是有序但效率慢,其中multi可以重复;而unordered版则是无顺序的,但是其优点速度快,其底层实现是哈希表。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值