【哈希表1】242.有效的字母异位词 349. 两个数组的交集 202. 快乐数 1. 两数之和

242.有效的字母异位词

题目链接

(1)文字讲解:https://programmercarl.com/0242.有效的字母异位词.html#思路
(2)视频讲解:
(3)题目链接:https://leetcode.cn/problems/valid-anagram/description/

看到题解之前的想法

用一个数组存字母以及出现的次数,两个句子得到两个数组,比较他们每一个元素(数组)的数量是否相同。

看到题解之后的想法

不需要两个数组计数,只需要在A字符串的时候++,B字符串的时候–就行,然后检查这个数组的每一个元素是否为0。

本题难点

当字符串中的元素有限时,你需要查找某个元素是否在字符串中,采用数据计数(哈希表)。

代码

class Solution {
public:
    bool isAnagram(string s, string t) {
        int record[26] = {0};
        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){
                return false;
            }
        }
        return true;
    }
};

349. 两个数组的交集

题目链接

(1)文字讲解:https://programmercarl.com/0349.两个数组的交集.html#算法公开课
(2)视频讲解:
(3)题目链接:https://leetcode.cn/problems/intersection-of-two-arrays/

看到题解之前的想法

不会写,完全不知道set的相关函数,而且这个题目的元素不像上一个题目一样是有限的,不可以用数组存放。

看到题解之后的想法

在这里插入图片描述
1.使用unordered_set存储nums1
2.对于nums2中的每一个元素,查询是否在这个set中,如果在,存到result_set中(因为nums2中的元素可能有重复,所以存放结果的也需要是set)
3.result_set转成vector

本题难点

unordered_set的基本操作

代码

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());
        for(int num : nums2){
            if(nums_set.find(num) != nums_set.end()){
                result_set.insert(num);
            }
        }
        return vector<int>(result_set.begin(), result_set.end());
    }
};

202. 快乐数

题目链接

(1)文字讲解:https://programmercarl.com/0202.快乐数.html#思路
(2)视频讲解:
(3)题目链接:https://leetcode.cn/problems/happy-number/

看到题解之前的想法

不知道怎么做

看到题解之后的想法

1.题目有提示,只有两种情况,无限循环和1。如果是无限循环,那么说明结果是重复出现的;也就是说,一旦重复出现,说明就不会返回1了
2.检查某个元素是否出现在某个集合中一定要想到用哈希表
3.思路很清晰了,将结果都存在orderset中,如果发现了有重复的,那就return false,否则return true。

本题难点

1.题意理解,只有重复出现和1两种情况
2.灵活运用哈希表

代码

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

1. 两数之和

题目链接

(1)文字讲解:https://programmercarl.com/0001.两数之和.html#算法公开课
(2)视频讲解:
(3)题目链接:https://leetcode.cn/problems/two-sum/description/

看到题解之前的想法

经过上面几题的历练,我想的是,用一个unordered_set先存储整个数组,然后遍历,如果target减去遍历到的元素得到的值能在set里面找到,那么记录这个元素的下标,退出循环,再次遍历数组,寻找到target-nums[i]这个数的下标(因为set只能提供找没找到,下标是不知道的),代码如下:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_set<int> nums_set(nums.begin(), nums.end());
        int i = 0, j = 0;
        for(; i< nums.size(); i++){
            if(nums_set.find(target-nums[i]) != nums_set.end())
            {
                break;
            }
        }
        int target_num = target-nums[i];
        for(int j = 0; j < nums.size(); j++){
            if(nums[j] == target_num){
                break;
            }
        }
        return vector<int>{i, j};
    }
};

但是这样是有问题的,如果遇到这样的示例:

也就是数组中有元素的两倍就等于target,那么在遍历到这个元素的时候,就算这个元素只出现了一遍,他就会返回这个函数的下标两次作为答案。因为,我先在set中将整个数组预存进去了,所以才会分不清楚元素出现了几次。

看到题解之后的想法

1.set不能存储下标,unordered_map更为合适,key是数据元素值,value是元素下标,这样可以根据key来寻找是否有需要的值,返回value
在这里插入图片描述
2.不是先把所有的数组元素预存在map中,而是,遍历数组,如果在当前的map中能找到当前元素的“互补”,那么返回找到的下标;否则将这个元素加到map中。这样就避免了上面我碰到的问题,就算是某个元素的两倍就等于target,也必须要第二次碰到这个元素才能成功。
3.按照这个思路,其实set也行,不是非要用map,就是要再遍历一遍数组找出来那个值。(不用担心当元素重复时,返回和上一轮遍历中相同的下标,因为上一轮找到的一定是第二个这个重复元素,我们按照顺序再次遍历只会找到第一个这个元素)

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_set<int> nums_set;
        int i = 0, j = 0;
        for(; i< nums.size(); i++){
            if(nums_set.find(target-nums[i]) != nums_set.end())
            {
                break;
            }else{
                nums_set.insert(nums[i]);
            }
        }
        int target_num = target-nums[i];
        for(; j < nums.size(); j++){
            if(nums[j] == target_num){
                break;
            }
        }
        return vector<int>{i, j};
    }
};

本题难点

1.想到使用map
2.不是预存所有元素值,而是先遍历,以避免一个元素的两倍恰好是target的情况。

代码

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++){
            auto iter = map.find(target-nums[i]);
            if (iter != map.end()){
                return {iter->second, i};
            }else{
                map.insert(pair<int, int>(nums[i], i));
            }
        }
        return {};
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值