算法_哈希表专题---持续更新

前言

本文记录leetcode哈希表刷题题解,包含 两数之和、判定是否互为字符重排、存在重复元素、存在重复元素II、字母异位词分组等题

引入

在本章中,会使用到 C++ 标准模板库 (STL) 中的一个关联容器unordered_map,提供了基于哈希表的键值对存储,主要会使用到的接口有:
operator[]: 通过键访问元素,如果键不存在则插入一个默认值
find(const Key& key): 查找指定键的元素,返回迭代器
count(): 返回指定键的元素数量
需要区别

unordered_map<string, vector<string>> hash;
hash[tmp].push_back(s);
hash[tmp] = s;

hash[tmp].push_back(s) 这行代码它的意思是:
首先检查 tmp 是否已经在 hash 映射中存在。
如果存在,那么这个操作会向对应的 vector 列表中添加新的元素 s。
如果 tmp 还不存在于映射中,一个新的键值对会被创建,其中 tmp 作为键,s 作为值

而 hash[tmp] = s; 表示的是直接将整个字符串 s 赋给 tmp 对应的值,也就是说 tmp 的值将会覆盖原有的 vector,如果之前存在的话,原来的所有元素都会被替换为单个的 s。

总结来说,两者的区别在于:
.push_back() 是在已有列表的基础上追加元素;

两数之和

https://leetcode.cn/problems/two-sum/

题目要求

题目解析

这道题是一道简单题,我们可以很自然地想到使用两个for循环解决,列举所有情况进行相加,看看值是否等于tartget,如果相等,就返回数组中对应的两个下标,暴力解法当然可以,但是还有时间复杂度更优的解法 查询,自然地想到用哈希表降低时间复杂度,如果使用哈希表一个循环就可以搞定(键key为数组元素的值,value值为下标),只需要遍历数组的时候,计算target目标值与当前循环对应元素的差,查找哈希表中是否有对应的值,如果有直接返回key对应的value以及当前循环的下标,没有就插入到哈希表中

代码如下

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) 
    {
        unordered_map<int, int> hash;
        for(int i = 0; i < nums.size(); i++)
        {
            int x = target - nums[i];
            //查找哈希表中是否存在键x
            if(hash.count(x)) return {hash[x], i};
            //将本轮循环的键插入哈希表中
            hash[nums[i]] = i;
        }
        //没找到
        return {-1, -1};
    }
};

判定是否互为字符重排

https://leetcode.cn/problems/check-permutation-lcci/description/

题目要求

在这里插入图片描述

题目解析

这道题的本质也是查询,无非就是查询s1与s2中每个字符出现的个数是否相等,查询的话我们使用哈希表是比较便利的,这里使用一个数组模拟哈希表,由于题目是小写字母,大小设为26即可,先遍历s1,将对应字符上的位置(表示元素个数)加1,然后遍历s2将字符对应位置(表示元素个数)减1,如果出现负数表明一个字符串不是另一个的重排字符串

代码如下

class Solution {
public:
    bool CheckPermutation(string s1, string s2) 
    {
        if(s1.size() != s2.size())
        {
            return false;
        }
        int hash[26] = {0};
        for(auto e : s1)
        {
            hash[ e - 'a']++;
        }
        for(auto e : s2)
        {
            hash[ e - 'a']--;
            if(hash[e - 'a'] < 0) return false;
        }
        return true;
    }
};

存在重复元素 I

https://leetcode.cn/problems/contains-duplicate/

题目要求

在这里插入图片描述

题目解析

这道题的意思是如果数组中出现重复的元素返回true,否则返回false,本题也很简单,只需查询数组中是否存在相同的元素即可 遍历数组,hash.count(nums[i])看看是否以及存在key,同时将数组中的元素插入哈希表中

代码如下

class Solution {
public:
    bool containsDuplicate(vector<int>& nums) 
    {
        unordered_map<int, int> hash;
        for(int i = 0; i < nums.size(); i++)
        {
        	//判断hash中是否存在nums[i]
            if(hash.count(nums[i])) return true;
            //插入哈希表中
            hash[nums[i]] = i;
        }
        return false;
    }
};

存在重复元素 II

https://leetcode.cn/problems/contains-duplicate-ii/

题目要求

在这里插入图片描述

题目解析

本题与上一题存在重复元素是类似的,如果数组中存在重复元素,并且下标的绝对值差值满足题目给定的k,那么返回true,否则返回false 与上一题做法相同,遍历数组并判断哈希表中是否有重复元素,下标差值是否小于等于k ## 代码如下
class Solution {
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) 
    {
        unordered_map<int, int> hash;
        for(int i = 0; i < nums.size(); i++)
        {
            if(hash.count(nums[i]) && abs(hash[nums[i]]-i) <= k)
            {
                return true;
            }
            //插入哈希表中
            hash[nums[i]] = i;
        }
        return false;
    }
};

字母异位词分组

https://leetcode.cn/problems/group-anagrams/

题目要求

在这里插入图片描述

题目解析

这道题题目要求是返回多组字符串数组,每一数组中字符串的字母异位词相同(字符串中包含的字符个数都相同),搜索、查找字母异位词,我们很自然地能想到用哈希表,遍历字符串数组,将ASCII 码排序之后作为key值存放在哈希表中,然后哈希表的value值是一个字符串数组,用来存储同一组异位词,最后遍历哈希表将value返回即可

在这里插入图片描述

代码如下

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) 
    {
        unordered_map<string, vector<string>> hash;
        for(auto& s : strs)
        {
            string tmp = s;
            sort(tmp.begin(), tmp.end());
            //每个键对应相应的值
            hash[tmp].push_back(s);
        }
        vector<vector<string>> ret;
        for(auto& [x, y] : hash)
        {
            ret.push_back(y);
        }
        return ret;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fan_558

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值