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

文章介绍了如何使用哈希表解决三个编程问题:判断字符串是否为字母异位词、找出两个数组的交集以及判断数是否为快乐数。主要解题策略是利用哈希表存储字符及其出现次数,对比数组元素,实现高效求解。
摘要由CSDN通过智能技术生成

242.有效的字母异位词

题目描述:
给定两个字符串 *s**t* ,编写一个函数来判断 *t* 是否是 *s* 的字母异位词。

**注意:**若 *s**t* 中每个字符出现的次数都相同,则称 *s**t* 互为字母异位词。

示例一:

输入: s = "rat", t = "car"
输出: false

示例二:

输入: s = "anagram", t = "nagaram"
输出: true

提示:

1 <= s.length, t.length <= 5 * 104
s 和 t 仅包含小写字母

解题思路:

  1. 关键词提取:每个字符、次数一致
  2. 哈希表解法:检索是否重复、检索次数,可以优先考虑哈希表法
    1. 首先判断两个数组长度是否一致
    2. 一致的情况下,建立一个数组模拟哈希表,原因是字符对应的数值有限,不会有溢出风险
    3. 同步检索两个数组,一个数组往哈希表中添加元素,一个数组往哈希表中删除元素
    4. 检查哈希表,如果两个数组的字符种类与个数一致,哈希表的元素的值都为零

代码如下:

class Solution {
public:
    bool isAnagram(string s, string t) {
        // 假如两个数组长度不一致
        if(s.size() != t.size()) {
            return false;
        }
        // 建立一个数组,模拟哈希表
        int stack[27] = {0};
        // 同步遍历两个数组,数组s往哈希表中增加计数,数组t往哈希表中删除元素计数
        for(int i = 0; i < s.size(); i++) {
            stack[s[i]-'a']++;
            stack[t[i]-'a']--;
        }
        // 检查哈希表中每个元素是否为0,若两个数组的字符种类与数量一致,就是0
        for(int i = 0; i < 27;i++) {
            if(stack[i] != 0) {
                return false;
            }
        }
        return true;
    }
};

总结:

  1. 二刷的时候,已经是一气呵成,一下子就把代码写出来,并且一次就AC。
    1)解题:每个字符、出现次数。
    2)不熟悉的时候,想的就是,暴力解法,对于每一个字符,都做一次遍历,并且统计次数。然后,再嵌套一个循环,在另一个数组那遍历该字符,并且统计次数。
    3)但是,现在脑海中会有哈希表法。题目的关注点在于种类和次数,假如我有一个表格,遍历一遍,将所有的元素都填进去,而且将次数统计出来。那,两个数组,我就用两个表格,最后比对两个表格就可以。
    4)再优化一下,就是,将两个表格合并为一个表格。先将第一个数组的元素填进去。再将第二个数组的元素从表格上擦除。看最后表格中还有没有多余的元素就可以。
  2. 代码随想录提供的就是哈希表法,关键点如下:
    1)采用数组做哈希表。
    2)根据字符大小,确认数组的大小。
    3)分别遍历两个字符数组。
    4)检查哈希表中元素的个数。

349.两个数组的交集

题目描述:
给定两个数组 nums1nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序

示例一:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

示例二:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

提示:

1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000

解题思路:

  1. 关键词提取:交集、结果唯一、不考虑顺序
  2. 哈希表法:
    1. 思路和上一题一样,采用数组做哈希表,提示中有规定数值大小,所以不需要调用哈希表的库函数
    2. 这题新增一个难点就是要去重,和上题稍微有一点不一样。所以这道题要先将一个数组的元素填充进哈希表。
    3. 再遍历另一个数组,从哈希表中将对应的元素删除掉,要单独做一个整体删除的动作。
    4. 所以一共做两次循环,第一次循环将元素填入表中,第二次循环从表上查找是否有对应元素,并且做好元素删除动作。
    5. 找对应元素不需要暴力遍历,直接检索哈希表索引即可。

代码如下:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        // 申请一个返回数组,记录元素
        int len = 0;
        vector<int> result(1001, 0);
        // 申请一个数组做哈希表
        int record[1001] = {0};
        // 将目标数组的值填充进哈希表中
        for(int i = 0; i < nums1.size(); i++) {
            record[nums1[i]]++;
        }
        // 在哈希表中,检索当前数组的值是否存在
        for(int j = 0; j < nums2.size(); j++) {
            // 检索到哈希表中有值,保存到返回数组红姑娘,同时,将哈希表中的值清零,代表已取用
            if(record[nums2[j]] > 0) {
                record[nums2[j]] = -1;
                result[len++] = nums2[j];
            }
        }
        // 对返回数组进行一次缩小
        vector<int> tmp(len, 0);
        for(int i = 0; i < len; i++) {
            tmp[i] = result[i];
        }
        return tmp;
    }
};

总结:

  1. 一刷和二刷都采用的这个方式。没有想着自己去编一个哈希表的函数,这个太折磨人了。写个简单的题目,用C语言,编写哈希表的各个操作,要一大堆代码。
    1)难点一:注意到限制条件,才能采用数组来做哈希表。否则容易溢出。
    2)难点二:去重的解决方案,脑海中老是告诉自己,要排序,才能做去重。但是实际上,只需要将哈希表中的元素删除,就可以达到去重的目的。哈希表的key是数字,value是出现的次数,将value清零,就是将元素删除。
  2. 代码随想录提供的是哈希表函数,需要用到对应的容器。
    1)我是只会C语言的,没怎么学过C++,这次也是借着写博客的这个过程,基于算法题去应用一下C++语言,从实践出发,反推自己去研究基础理论知识。所以我没法基于C++语言,对题目考查的知识点,作出回应。更多的是对于算法以及C语言的知识点,作出的解释。请见谅。
    2)看了下,C++语言还是好呀,蛮方便的,可以用容器去实现哈希,可以用库函数去做插入而不用考虑数组大小,可以用库函数去去重,而不用自己去排序、循环检索去重。有兴趣的小伙伴可以看下解析。
    3)代码随想录讲解视频:https://www.bilibili.com/video/BV1ba411S7wu

202.快乐数

题目描述:
编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

  • 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
  • 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
  • 如果这个过程 结果为 1,那么这个数就是快乐数。

如果 n快乐数 就返回 true ;不是,则返回 false

示例一:

输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

示例二:

输入:n = 2
输出:false

提示:

1 <= n <= 231 - 1

解题思路:

  1. 关键词提取:每个位置的平方、替换为所有位置的平方和、会无限循环
  2. 解法:
    1. 需要封装一个函数,取每个位置的数值
    2. 将每个位置的数值求平方,并且累加
    3. 将值存放到哈希表中
    4. 假如某个数值出现过第二次,说明进入死循环

代码如下:

class Solution {
private:
    // 计算每个数字的平方,并且求和
    int getNum(int n) {
        int sum = 0;
        while(n) {
            // 取个位的数字
            int tmp = n % 10;
            // 累加每个位置数字的平方
            sum += tmp * tmp;
            // 将取完的数字删除掉
            n = n / 10;
        }
        return sum;
    }
public:
    bool isHappy(int n) {
        unordered_set<int> set;
        int sum = 0;
        while(1) {
            sum = getNum(n);
            // 假如平方和为1,即符合题目要求
            if(sum == 1) {
                return true;
            }
            // 检索哈希表中是否有sum值,有的话意味着进入无限循环
            if(set.find(sum) != set.end()) {
                return false;
            }
            // 将值插入到哈希表中
            else {
                set.insert(sum);
            }
            // 更新n值
            n = sum;
        }
    }
};

总结:

  1. 二刷,可以快速写出解法,但是不知道怎样转换成代码,痛苦。
  2. 代码随想录提供的是哈希表函数,需要用到对应的容器。
    1)难点一:需要注意怎么取各个位置的数字。
    2)难点二:需要理解题目中无限循环的含义,需要转换成一个平方和出现第二次。

1.两数之和

题目描述:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例一:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例二:

输入:nums = [3,2,4], target = 6
输出:[1,2]

提示:

2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案

解题思路:

  1. 关键词提取:目标值、两个数求和、下标、答案唯一、元素不重复
  2. 解法:
    1. 采用哈希表做,键对中,键值是整数值,参数是数组下标
    2. 遍历数组,将目标值与当前值作差,在哈希表中寻找差值
    3. 若找到差值,就返回数组下标,否则就将当前元素添加进入哈希表中

代码如下:

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};
            }
            // 若找不到差值,就将当前值与下标插入到哈希表中
            map.insert(pair<int, int>(nums[i], i));
        }
        return {};
    }
};

总结:

  1. 二刷,可以快速写出解法,但是不知道怎样转换成代码,痛苦。暴力法虽好,但是容易超时。采用C写哈希表,需要调用库函数,蛮痛苦的一个过程。
  2. 代码随想录提供的是哈希表函数,需要用到对应的容器。
    1)难点一:需要注意到哈希表的容器选择,需要key和value。
    2)难点二:需要注意到key存的是元素值,value存的是下标。
  • 18
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值