算法—哈希表

目录

两数之和

判定是否互为字符重排

存在重复元素

[存在重复元素 II](#存在重复元素 II)

字母异位词分组

两数之和

思路: 这道题的的暴力解法可以使用双指针,其中一个指针固定数字中的一个元素,另一个指针从这个固定的数的前一个位置开始向前遍历,判断两指针指向元素相加是否等于目标值,如果第二个指针遍历结束还没有符合条件的值,就继续固定下一个数。这种暴力解法可以使用哈希表优化,判断被固定的数前面有没有元素和它相加等于目标值,其实就是判断固定的数前面有没有一个数等于目标值减去当前固定的值。**优化:**创建一个哈希表,存储数组元素和下标的映射,每次判断目标值减去当前固定的值的结果在哈希表中有没有,有就可以直接返回结果,没有就将这个固定的数放进哈希表,继续固定下一个数。

代码:

cpp 复制代码
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> hash;
        for(int i = 0; i < nums.size(); i++){
             if(hash.count(target - nums[i])){
                return {hash[target - nums[i]], i};
             }
             hash[nums[i]] = i;
        }

        return {-1, -1};
    }
};

判定是否互为字符重排

**思路:**创建两个数组模拟哈希表,分别存储两个字符串中每个字符的数量,然后遍历两个数组是否相等就可以了。(使用一个数组也可以,第一个字符串每个字符数量加到数组中,然后从数组中减去第二个字符串中每个字符的数量,如果减完后数组中有负数,说明两个字符串不相等)

**优化:**当两个字符串字符总数不相等时直接返回 false 即可。

代码:

cpp 复制代码
class Solution {
public:
    bool CheckPermutation(string s1, string s2) {
        int hash1[26] = { 0 };
        int hash2[26] = { 0 };

        for(auto ch : s1){
            hash1[ch - 'a']++;
        }
        for(auto ch : s2){
            hash2[ch - 'a']++;
        }

        for(int i = 0; i < 26; i++){
            if(hash1[i] != hash2[i])
                return false;
        }

        return true;
    }
};

存在重复元素

**思路:**因为只要有一个数出现两次就算重复了,所以只需要创建一个哈希表存储 key(即数组元素) 即可,遍历数组向哈希表中放元素,只要某个元素放入之前就已经在哈希表中存在就是重复了。

代码:

cpp 复制代码
class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        unordered_set<int> hash;
        for(auto num : nums){
            if(hash.count(num))
                return true;
            hash.insert(num);
        }

        return false;
    }
};

存在重复元素 II

**思路:**这道题的暴力解法还是双指针,一个指针固定数组中的某个元素,另一个指针遍历当前元素前面是否有符合条件的值。基于这种暴力解法,我们使用哈希表(存储元素和下标的映射)优化,遍历数组,如果当前被遍历的元素在哈希表中,判断是否符合条件,不符合条件或者哈希表中不存在该元素就将这个元素放入哈希表。

**为什么相同元素不符合条件时直接更新哈希表:**如果当前遍历的元素在哈希表中已经存在,但是它们的距离查不符合条件,将当前元素和下标的映射更新到哈希表中即可,因为数组是从前向后遍历的,下一个相同的元素一定在后面,哈希表中已经存储的那个元素一定在当前遍历的元素的前面,所以如果后面还有相同的元素,当前遍历到的这个会离它更近,更可能符合条件,所以更新。

代码:

cpp 复制代码
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]) && i - hash[nums[i]] <= k)
                return true;

            hash[nums[i]] = i;
        }

        return false;
    }
};

字母异位词分组

**思路:**使用哈希表,存储每个字符串排好序后的样子和所有对应的没排序的字符串的映射。

代码:

cpp 复制代码
class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string, vector<string>> hash;
        for(auto str : strs){
            string tmp = str;
            sort(tmp.begin(), tmp.end());
            hash[tmp].push_back(str);
        }

        vector<vector<string>> ret;
        for(auto pair : hash){
            ret.push_back(pair.second);
        }

        return ret;
    }
};
相关推荐
SilentSamsara18 分钟前
Python 环境搭建完整指南:从下载安装到运行第一个程序
开发语言·python
小短腿的代码世界32 分钟前
Qt文件系统与IO深度解析:从QFile到异步文件操作
开发语言·qt
智者知已应修善业1 小时前
【51单片机按键调节占空比3位数码管显示】2023-8-24
c++·经验分享·笔记·算法·51单片机
JasmineX-12 小时前
数据结构(笔记)——双向链表
c语言·数据结构·笔记·链表
harder3212 小时前
RMP模式的创新突破
开发语言·学习·ios·swift·策略模式
.5482 小时前
## Sorting(排序算法)
python·算法·排序算法
jinanwuhuaguo2 小时前
OpenClaw工程解剖——RAG、向量织构与“记忆宫殿”的索引拓扑学(第十三篇)
android·开发语言·人工智能·kotlin·拓扑学·openclaw
Rust研习社2 小时前
使用 Axum 构建高性能异步 Web 服务
开发语言·前端·网络·后端·http·rust
wuweijianlove2 小时前
算法的平均复杂度建模与性能回归分析的技术7
算法·数据挖掘·回归
子琦啊2 小时前
【算法复习】字符串 | 两个底层直觉,吃透高频题
linux·运维·算法