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

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


242.有效的字母异位词

题目链接:242.有效的字母异位词

解题思路

定义一个数组(数组就是简单的哈希表)来记录字符串 s 中字符出现的次数。因为字本题中字符串均为小写字母,所以可以定义一个长度为26的数组,将字符映射到数组的索引上,字符 a 到字符 z 的 ASCII 值是26个连续的数值,字符 a 映射为索引0,字符 z 映射为索引25。

遍历字符串时,对 s[i]-‘a’ 所在的元素做 +1 处理,这样就可以将字符串 s 中字符出现的次数统计出来。在遍历字符串 t 时,对 t 中出现的字符映射到数组索引中的数值做 -1 操作。若数组中所有元素均为0,说明是有效的字母异位词。

代码实现
class Solution {
public:
    bool isAnagram(string s, string t) {
        int A[26] = {0};
        for (int i = 0; i < s.size(); i++) {
            A[s[i] - 'a']++;
        }
        for (int i = 0; i < t.size(); i++) {
            A[t[i] - 'a']--;
        }
        for (int i = 0; i < 26; i++) {
            if (A[i] != 0) {
                return false;
            }
        }
        return true;
    }
};
题目总结

暴力解法两层 for 循环还要记录元素出现的次数复杂度过高,用哈希表,且对 s[i]-‘a’ 所在的元素做处理的操作会大大简化复杂度。

349.两个数组的交集

题目链接:349.两个数组的交集

解题思路

题目中提到输出结果是唯一的,且不考虑输出结果的顺序,也就是说输出的结果是去重的,可以使用 set 数据结构,unordered_set 的底层实现是哈希表, 使用 unordered_set 读写效率是最高的,且不需要对数据进行排序,而且不要让数据重复,所以选择unordered_set。

代码实现
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result;
        unordered_set<int> nums(nums1.begin(), nums1.end());
        for (int i : nums2) {
            if (nums.find(i) != nums.end()) {
                result.insert(i);
            }
        }
        return vector<int>(result.begin(), result.end());
    }
};
题目总结

将一个数组转成 set,另一个数组用来遍历,将交集元素存入新 set。

202.快乐数

题目链接:202.快乐数

解题思路

本题中提到会无限循环,在求和过程中,sum 会重复出现,但当 sum 重复出现时,本数就不符合快乐数的要求,本题使用哈希来记录 sum 值。

代码实现
class Solution {
public:
    int getSum(int n) {
        int sum = 0;
        while (n) {
            sum += (n % 10) * (n % 10);
            n /= 10;
        }
        return sum;
    }

    bool isHappy(int n) {
        unordered_set<int> set;
        while (1) {
            int sum = getSum(n);
            if (sum == 1) {
                return true;
            }
            if (set.find(sum) != set.end()) {
                return false;
            } else {
                set.insert(sum);
            }
            n = sum;
        }
    }
};
题目总结

注意求和的过程,还有取数值上各个位数的操作。

1.两数之和

题目链接:1.两数之和

解题思路

第一种方法暴力解法,两层for循环, if 判断两数之和是否为目标值。

第二种方法哈希解法,由于本题不仅要判断两数是否存在,还要返回符合条件的两数的下标,所以需要考虑另一种数据结构 map,用 key 保存数值,用 value 记录数值所在的下标。且这里不需要有序,所以选择 unordered_map。

代码实现

暴力解法

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        for (int i = 0; i < nums.size(); i++) {
            for (int j = i + 1; j < nums.size(); j++) {
                if (nums[i] + nums[j] == target) {
                    return {i, j};
                }
            }
        }
        return {};
    }
};

哈希解法

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        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 {};
    }
};
题目总结

当需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,要第一时间想到哈希法。本题需要一个集合来存放遍历过的元素,然后在遍历数组的时候去询问这个集合,某元素是否遍历过,也就是 是否出现在这个集合。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值