算法—哈希表

目录

两数之和

判定是否互为字符重排

存在重复元素

[存在重复元素 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;
    }
};
相关推荐
一直C几秒前
Linux系统编程|信号进阶 + SystemV IPC(消息队列、共享内存)
linux·c语言·开发语言·算法·青少年编程·vim
小+不通文墨9 分钟前
使用vscode里的U8G2 库编写OLED菜单控制
经验分享·笔记·单片机·嵌入式硬件·学习
小王C语言15 分钟前
QT 基础:QT SDK 下载、配置、新建项目、项目代码解释
开发语言·qt
葡萄成熟时 !30 分钟前
泛型知识笔记
开发语言·笔记·python
北风toto41 分钟前
扩展操作码技术 · 详细笔记
运维·服务器·笔记·软件设计师
新时代牛马1 小时前
SPL-TPL 链式启动:spl.c 与CONFIG_TPL 三阶段加载
c语言·开发语言
布莱克6051 小时前
链表详解:定义、作用、应用场景及与数组的区别(C/C++ 实战)
c语言·开发语言·c++·链表
2601_966949651 小时前
实时行情中的成交量 Volume 到底是什么?包含盘中撤单量吗?从交易数据语义到 QuantDash 实战解析
开发语言·人工智能·python·量化·quantdash·量化数据源
鹿角片ljp1 小时前
LeetCode 141. 环形链表|从 HashSet 到快慢指针 O (1) 空间最优解
算法·leetcode·链表
薛定e的猫咪1 小时前
(NeurIPS 2022)GraphGPS:MPNN 与全局注意力的融合之道
人工智能·深度学习·学习·算法