算法—哈希表

目录

两数之和

判定是否互为字符重排

存在重复元素

[存在重复元素 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;
    }
};
相关推荐
青槿吖1 分钟前
第二篇:Spring MVC进阶:注解、返回值与参数接收的花式玩法
java·开发语言·后端·mysql·spring·mvc·mybatis
共享家95272 分钟前
Java入门(抽象类 与 接口)
java·开发语言
hanbr3 分钟前
C++ string类模拟实现(完整版,含全运算符重载)
java·开发语言
xUxIAOrUIII4 分钟前
【Go每日面试题】内存管理
java·开发语言·golang
勇闯逆流河5 分钟前
【Linux】linux进程概念(fork,进程状态,僵尸进程,孤儿进程)
linux·运维·服务器·开发语言·c++
森屿山茶5 分钟前
hot100题解 —— 146.LRU缓存
java·开发语言
70asunflower6 分钟前
CUDA基础知识巩固检验练习题【附有参考答案】(7)
c++·人工智能·cuda
buyulian10 分钟前
Bug防御体系:技术方案的优与劣
java·经验分享·bug·软件工程
superkcl202210 分钟前
C++初始化 和 赋值
开发语言·c++·算法
童话名剑10 分钟前
YOLO v5(学习笔记)
笔记·学习·yolo