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

242.有效的字母异位词

题目链接:https://leetcode.cn/problems/valid-anagram/description/

思路:首先要明确字母异位词的定义,即两字符串中的每个字符出现的次数相同。考虑到字符会重复出现,这时需要用到哈希法,该题的字符较少,可以用数组这一数据结构。数组大小为26,对应a-z这26个连续的字母。在遍历字符串s的时候,只需要将 s[i] - ‘a’ 所在的元素做+1 操作即可,并不需要记住字符a的ASCII,只要求出一个相对数值存放在数组中。

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;  //record数组中的所有元素都为0,说明两字符串是字母异位词
        }          
};

349. 两个数组的交集

题目链接:https://leetcode.cn/problems/intersection-of-two-arrays/description/

思路:该题用到了一个哈希法新的数据结构,即set(集合),unordered_set。std::unordered_set的底层实现是哈希表, 使用unordered_set 读写效率是最高的,并不需要对数据进行排序,而且还不要让数据重复,所以选择unordered_set。该题出现了迭代器的概念,由于没有接触过,所以这到题感觉很难。

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) { //使用set结构体作哈希表来处理没有限制数值的问题
        unordered_set<int> result_set;   //存放结果,set能给结果去重
         unordered_set<int> nums_set(nums1.begin(), nums1.end());  //创建nums_set 将nums1数组中的元素添加到其中,nums1.begin()和nums1.end()分别表示nums1数组的起始和结束迭代器。
        for (int num : nums2) {  //范围基于循环  遍历nums2数组中的每个元素,将每个元素赋值给变量num。
            // 发现nums2的元素 是否在nums_set里出现过    ==end了就说明set里面没有这个元素。
            if (nums_set.find(num) != nums_set.end()) {
                result_set.insert(num);
            }
        }
        return vector<int>(result_set.begin(), result_set.end()); //unordered_set<int>是一个无序集合,不保持元素的插入顺序。vector<int>是一个有序的动态数组,保持元素的插入顺序。 unordered_set 来存储交集结果,以便去重。函数的返回类型要求是 vector<int>,因此我们需要将 result_set 转换为这种类型。
    }
};

202. 快乐数

题目链接:https://leetcode.cn/problems/happy-number/

思路:先要写一个求取数值各个位上的单数之和的函数。然后要判断sum是否会重复出现集合里,重复了就是return false,没重复直接找到sum等于1为止。所以需要考虑哈希法。哈希法的数据结构采用unordered_set。注意无限循环的条件while(1)及跳出循环的条件。

class Solution {
public:
    int getSum(int n){
      int sum = 0;
        while(n>0){  //取数值各个位上的单数之和(正整数)
        sum += (n%10)*(n%10);
        n = n/10;
        }
        return sum;
    }
    bool isHappy(int n) {
      unordered_set<int> set;
      while(1){ //无限循环,当条件为真,一直执行循环体中的语句  直到程序被强制停止或满足特定条件才退出循环。
        int sum = getSum(n);
        if(sum == 1){
            return true;
        }
        //如果这个sum出现过,说明已经进入无限循环,立刻false;  set.end()指向null;
        if(set.find(sum) != set.end()){//sum在set中都没有出现过
            return false;
        }else {
            set.insert(sum);  //将sum插入set容器中
        }
        n = sum;   //保证循环的执行
      }
    }
};

1. 两数之和

题目链接:https://leetcode.cn/problems/two-sum/

思路:该题较难,用到了哈希法里的map数据结构,map中的数据是以<key,value>形式储存的,key来存元素,value来存下标,同时也用到了迭代器的概念。std::unordered_map 底层实现为哈希表。map目的用来存放我们访问过的元素,因为遍历数组的时候,需要记录我们之前遍历过哪些元素和对应的下标,这样才能找到与当前元素相匹配的(相加等于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++){//遍历当前元素,在map中寻找是否有匹配的key
           auto iter = map.find(target-nums[i]);  //iter作为一个迭代器,其指向哈希表中的某个元素,
           if(iter != map.end()){   //如果 iter 不等于哈希表的 end(),说明找到了对应的差值,可以继续处理。
            return {iter->second, i};  //数组中的值以<key,value>保存到map中去,iter->second 表示该元素的第二个值,也就是哈希表中存储的索引。返回一个包含两个整数的数组,第一个整数是哈希表中存储的索引,第二个整数是当前遍历的数组索引。
           }//如果没找到匹配对,就把访问过的元素和下标加入到map中
            map.insert(pair<int,int>(nums[i],i));  //pair用于存储两个不同类型的值。
        }
        return {};
    }
};

总结:什么时候使用哈希法,当我们需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要第一时间想到哈希法。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值