当前位置: 代码网 > it编程>软件设计>算法 > LeetCode Day6 哈希表: 242.有效的字母异位词,349. 两个数组的交集,202. 快乐数,1. 两数之和

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

2024年07月31日 算法 我要评论
242.有效的字母异位词。

目录

哈希表理论基础

242.有效的字母异位词

(1) 题目描述 

(2) 解题思路

349. 两个数组的交集

(1) 题目描述 

(2) 解题思路

202. 快乐数

(1) 题目描述 

(2) 解题思路

1. 两数之和 

(1) 题目描述 

(2) 解题思路


哈希表理论基础

242.有效的字母异位词

(1) 题目描述 

leetcode 242. 有效的字母异位词

代码随想录:(文字版)

代码随想录:(视频版)

(2) 解题思路

解题步骤:

1. 暴力解法

  • 第一层for循环: 遍历s中的元素
  • 第二层for循环: 遍历t中的元素,判断s中元素是否在t中出现。注意判断字母是否重复。

 2. 哈希表

哈希表: 快速判断一个元素是否出现集合里。

本题目只有26个字母,数值小,范围可控 --> 数据结构使用数组

数组大小: 字符a到字符z的ascii是26个连续的数值 -->数组大小为26,初始化为0。

class solution {
public:
    bool isanagram(string s, string t) {
        // 哈希表法
        // (1) 定义大小为26的数组作为哈希表,因为字母为26个,初始值均为0,字母a位于哈希表数组下标为0的位置。
        int record[26] = {0};
        // (2) 统计在s中字母的出现次数,出现一次加1
        for (int i = 0; i < s.size(); i++){
            // s[i]: s中第i个字符的ascii码
            //'a': 字符a的ascii码(计算机内部的二进制表示)
            record[s[i]-'a']++; // s[i]-'a': s中第i个字符在字母表的位置,即record中对应字符的下标位置
        }
        // (3) 统计在t中字母的出现次数,出现一次在哈希表中减1
        for (int i = 0; i < t.size(); i++){
            record[t[i]-'a']--;
        }
        // (4) 根据哈希表中的数值判断结果
        // (4.1) record数组如果有的元素不为零0,说明字符串s和t一定是谁多了字符或者谁少了字符。
        for (int i = 0; i < 26;i++){
            if(record[i] != 0){
                return false;
            }
        }
        // (4.2) record数组所有元素都为零0,说明字符串s和t是字母异位词
        return true;
    }
};

349. 两个数组的交集

(1) 题目描述 

leetcode 349. 两个数组的交集

代码随想录:(文字版)

代码随想录:(视频版)

(2) 解题思路

题目说明:输出结果中的每个元素一定是唯一的,即去重(无序)

1. 数据结构set

使用unordered_set: 读写效率是最高的,不重复,无序,且不能更改数值。

c++去重容器 unordered_set 用法概述

cppreference: std::unordered_set

class solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        // 数据结构set
        // (1) 定义unordered_set存放结果,用set是给结果集去重
        unordered_set<int> result_set;
        // (2) 用unordered_set构造哈希表,将nums1中数据映射到哈希表
        unordered_set<int> nums_set(nums1.begin(), nums1.end());
        // (3) 用for循环遍历nums2中元素,检测每个元素是否是交集元素
        for (int i = 0; i < nums2.size(); i++){
            int num = nums2[i];     // * 上面和这行等效于 for (int num: nums2)
            // (4) 检查nums2中的元素num是否在nums1映射的哈希表nums_set中出现过,如果出现,则是交集元素,将其存入结果集
                // 注意: set.end() 返回的是最后的index的下一个, 即是不存在的;
                // set.find(x) = set.end(): 没找到;
            if (nums_set.find(num) != nums_set.end()){
                result_set.insert(num);
            }
        }
        // (5) 转换为题目要求的数据结构
        return vector<int>(result_set.begin(), result_set.end());
    }
};

2. 数据结构数组

使用条件:  本题后面 数值范围有限:

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

优点: 运算速度

class solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        // 数据结构数组
        // (1) 定义unordered_set存放结果,用set是给结果集去重
        unordered_set<int> result_set;
        // (2) 用数组构造哈希表,将nums1中数据映射到哈希表,数组大小比题目条件中的1000稍大即可,初始化均为0
        int hash[1001] = {0};
        // (3) 用for循环遍历nums1中元素,出现的字母在hash数组中做记录
        for(int num:nums1){
            hash[num] = 1;
        }
        // (4) 用for循环遍历nums2中元素,当nums2中元素在nums1中出现时,将其加入结果集
        for (int i = 0; i < nums2.size(); i++){
            int num = nums2[i];     // * 上面和这行等效于 for (int num: nums2)
            if (hash[num] == 1){
                result_set.insert(num);
            }
        }
        // (5) 转换为题目要求的数据结构
        return vector<int>(result_set.begin(), result_set.end());
    }
};

202. 快乐数

(1) 题目描述 

leetcode 202. 快乐数

代码随想录:(文字版)

(2) 解题思路

基本解法思路:

  • 求该数字的每一位的平方和,得到新数字
  • 将新数字更新,重复上一步,直到判断结果是否为1

 但难点在于该数字会陷入无限循环 --> 使用哈希表判断该数字是否出现过,出现则表示已经开始无限循环,返回false。 

class solution {
public:
    // 取数值各个位上的单数之和
    int getsum(int n) {
        int sum = 0;
        while (n) { // 一直循环,直到取完n的每个位置的平方和
            sum += (n % 10) * (n % 10); // n % 10: n除以10以后的余数(取余) --> 个位的数
            n /= 10; // n /= 10: 相当于n=n/10,是得到n除以10的商的整数部分(取整)--> 将n去掉个位剩下的数。如19 --> 1
        }
        return sum;
    }
    bool ishappy(int n) {
        // 哈希表
        // (1) 定义unordered_set来判断sum是否重复出现,避免陷入无限循环
        unordered_set<int> set;
        // (2) 循环求数字n的每一位的平方和sum,得到后更新数字n,直到找到结果
        while(1) {
            int sum = getsum(n);
            // (2.1) 找到最终结果为1的快乐数
            if (sum == 1) {
                return true;
            }
            // (2.2) 使用哈希表检查sum是否重复出现,当开始无限循环时
            if (set.find(sum) != set.end()) { // 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false
                return false;
            } else {
                set.insert(sum); // 如果这个sum没有出现过,将其加入哈希表来帮助接下来的判断
            }
            n = sum; // 更新数字n,直到找到结果
        }
    }
};

1. 两数之和 

(1) 题目描述 

leetcode 1. 两数之和

代码随想录:(文字版)

代码随想录:(视频版)

(2) 解题思路

1. 暴力解法

class solution {
public:
    vector<int> twosum(vector<int>& nums, int target) {
        // 暴力解法
        // (1) 定义根据题目,结果为两个下标
        vector<int> result(2, 0);
        // (2) 两层for循环,找到两个元素和为目标值
        for (int i = 0; i < nums.size(); i++){
            int sum = 0;
            for (int j = i + 1; j < nums.size(); j++){ // 注意,j的初始值为i+1,因为元素不能重复
                sum = nums[i] + nums[j];
                if (sum == target){
                    result[0] = i;
                    result[1] = j;
                    break; // 题目说明,只存在一个答案,故一旦找到即可break
                }
            }
        }
        return result;
    }
};

2. 哈希表map

  •   为什么会想到用哈希表
    •  本题需要一个集合来存放遍历过的元素,然后在遍历数组的时候去询问这个集合,某元素是否出现在这个集合 --> 哈希表
  • 哈希表为何用map
  • map类型
    • 本题不需要key有序,选择std::unordered_map 效率更高
  • map中的key和value用来存什么的
    • key:  判断key是否出现     value: key对应信息   
    •   map中的存储结构为 {key:数据元素,value:数组元素对应的下标。
class solution {
public:
    vector<int> twosum(vector<int>& nums, int target) {
        // 哈希表map
        // (1) 定义map哈希表,kay存放元素,value存放下标
        std::unordered_map<int, int> map;
        // (2) 遍历nums中元素,并寻找与其和为target的另一个元素,使用哈希表查询另一个元素是否已经遍历到
        for(int i = 0; i < nums.size(); i++){
            // 寻找与其和为target的另一个元素
            auto iter = map.find(target - nums[i]); // //find返回的是迭代器,即指针
            // 使用哈希表查询另一个元素是否已经遍历到,
            if (iter != map.end()){ 
                // 当发现已经出现过,返回结果值
                return {iter->second, i};  //用迭代器访问pair的first或者second成员方法是:iter->first或iter->second
            }
            // 当发现没有出现过,将当前元素加入map
            map.insert(pair<int, int>(nums[i], i));
        }
        return {};
    }
};

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com