代码随想录算法训练营第六天|242.有效的字母异位词、349. 两个数组的交集、202. 快乐数、1. 两数之和

本文介绍了使用哈希表解决编程题目的几个示例,包括判断有效字母异位词、找到两个数组的交集、判断快乐数以及寻找两数之和。哈希表在这些问题中用于快速查找和统计元素,例如使用unordered_map存储元素及其索引,或unordered_set记录元素出现频率。
摘要由CSDN通过智能技术生成

目录

242.有效的字母异位词

349. 两个数组的交集 

202. 快乐数

1. 两数之和 


242.有效的字母异位词

题目链接:力扣242

如果两个字符串为s和t,我们需要判断s中出现的字母有没有在t中出现,且二者出现的次数要相等。而一般哈希表都是用来快速判断一个元素是否出现集合里,此处便可使用哈希表这个方法。

一共有26个英文字母,数量比较少,因此可以采用数组哈希表的方法,把ASCII码作为这个字母的下标,数组中存储字母出现的次数。

判断s和t是否为字母异位词可以转换为,判断s和t各个字母出现的频率是否一致。为方便比较,可以先遍历统计s字符串中各字母的频率,采取+1计数;再遍历t字符串中各字母的出现频率,采取-1计数。这样,再遍历一次,检查哈希表数组中各字母是否出现频率为0,即可实现目的。

class Solution {
public:
    bool isAnagram(string s, string t) {
        int hash[26];
        for(int i=0;i<26;i++){
            hash[i]=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. 两个数组的交集 

力扣349

这道题如果还用数组的话, 返回的交集是没有去重的。但题目要求返回交集是去重的。

为什么想到要用哈希表来解决这个题目呢?一般哈希表都是用来快速判断一个元素是否出现集合里。所以此处应该很快get到要用哈希表的方法。

接下来考虑用数组 or   set   or  map

数组下标做映射的缺点是:当个数非常非常多,或者数与数之间分散得特别开的时候,会浪费特别多存储空间。此处选择set作为哈希表。关于set的选择:参考代码随想录哈希表理论基础

此处选择unordered_set这种映射和取值效率都很高的数据结构。它可以自动处理重复元素,确保结果中的元素是唯一的。

整道题的思路就是:nums1进行处理转变为哈希表的形式,存储nums1中的所有元素。然后再用nums2遍历每一个元素去查询这个哈希表中是否出现过。如果出现过,就将这个元素放进result集合中。

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

unordered_set<int> nums_set(nums1.begin(), nums1.end());:这创建了另一个无序集合,并使用nums1中的元素进行初始化。这个集合用于检查nums2中的元素是否存在于nums1中。

for (int num : nums2) :这开始一个循环,遍历nums2中的每个元素num

if (nums_set.find(num) != nums_set.end()) :这个条件检查nums2中的元素num是否在nums_set中存在,而nums_set包含了nums1的元素.

最后return的部分:将 result_set 中的元素复制到了新的 vector<int> 中。vector<int>(result_set.begin(), result_set.end()) 这个操作创建了一个从 result_set 集合中所有元素的拷贝的向量。

  • result_set.begin(): 这是一个迭代器,指向 result_set 集合中的第一个元素。
  • result_set.end(): 这也是一个迭代器,指向 result_set 集合中最后一个元素之后的位置(末尾标记位置)

202. 快乐数

力扣202

这个题目的重点在于认识到:

如果在求和的过程中,sum会重复出现,就已经不是快乐数了

注意这里的sum重复出现,需要我们快速判断一个元素是否出现在集合里,也就是哈希法的范畴。

所以这道题目使用unordered_set来应用哈希法。

class Solution {
public:
    int getsum(int num){
        int sum=0;
        while(num){
            sum+=(num%10)*(num%10);
            num = num/10;
        }
        return sum;
    }
    bool isHappy(int n) {
        unordered_set<int> result;
        while(1){
            int sum = getsum(n);
            if(sum==1){
                return true;
            }
            if(result.find(sum)!=result.end()){//sum已经出现过,已陷入循环
                return false;
            }else{
                result.insert(sum);
            }
            n = sum;
        }
    }
};

1. 两数之和 

例如{2,3,7},target=9;

大致思路是,轮到数组的这个数num(例7)的时候,去找数组有没有遍历过target-num(例9-7=2)这个数,如果有,则存在两数之和的这两个数。

“去找数组有没有遍历过target-num这个数”这句话就暗示我们,可以采用哈希表进行查找。

那么如何查找呢?题目要求我们返回这两个数的数组下标,而我们在遍历查找时target-num又需要这个值(2),所以哈希表采用的数据结构就必须把这两个信息都存储起来。由于查找采用的是target-num这个数值,那我们就可以利用map->firs也就是map的key来放数值,map->second也就是map的value来放数值的下标信息。

如果找到了通过target-nums【i】这个k值能找到,说明之前已经遍历过的某个元素和当前元素的和等于 target。因此,直接返回这两个元素的下标。如果没匹配到,也一定要记得把访问过的元素和下标存入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 t = target-nums[i];
            if(map.find(t)!=map.end()){
                return {map.find(t)->second, i};
            }
            // 没匹配到,就把访问过的元素和下标加入到map中
            map.insert(pair<int, int>(nums[i], i));
        }
        return {};
    }
};

本文参考代码随想录

感想

本次练习哈希表的应用思路都很清晰,但由于是第一次使用unordered_map,unordered_set这种数据结构,即便知道了思路,还是不能很顺手的写出来,还不太熟悉它的操作,需要多用几次。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值