算法—哈希表

目录

两数之和

判定是否互为字符重排

存在重复元素

[存在重复元素 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;
    }
};
相关推荐
错把套路当深情几秒前
Kotlin 全方向开发技术栈指南
开发语言·kotlin
wayz112 分钟前
数据分析中的异常值处理:MAD
算法·数据挖掘·数据分析
飞Link6 分钟前
LangGraph 核心架构解析:节点 (Nodes) 与边 (Edges) 的工作机制及实战指南
java·开发语言·python·算法·架构
ZhiqianXia8 分钟前
Pytorch 学习笔记(8): PyTorch FX
pytorch·笔记·学习
Mr_Xuhhh28 分钟前
深入理解二叉树:从数据结构到算法实战
数据结构·算法
xuhaoyu_cpp_java30 分钟前
Boyer-Moore 投票算法
java·经验分享·笔记·学习·算法
武藤一雄38 分钟前
WPF中ViewModel之间的5种通讯方式
开发语言·前端·microsoft·c#·wpf
XiYang-DING40 分钟前
【Java】堆
java·开发语言
Lyyaoo.1 小时前
【Java基础面经】Java 反射机制
java·开发语言·python
雨浓YN1 小时前
OPC UA 通讯开发笔记 - 基于Opc.Ua.Client
笔记·c#