【算法】哈希表专题

一. (1.) 两数之和

算法原理:

1.暴力解法:从前往后

用两遍for循环,固定一个数,在这个数之前遍历看是否相加等于目标值,正反遍历都可以,但哈希表优化是基于反向遍历的

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

2.哈希表优化

直接将固定数前面的数都放入哈希表中,查找哈希表中是否存在值为target-固定数的元素,有就直接返回两数下标,没有就将固定数放入哈希表中。这样的好处不用每一个数都要遍历一次数组查找,直接查找一次哈希表即可,时间复杂度从n方降为n,空间复杂度为n,哈希表是以空间换时间的策略

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 {};
    }
};

二. (⾯试题 01.02.) 判定是否互为字符重排

算法思路:

  1. 当两个字符串的⻓度不相等的时候,是不可能构成互相重排的,直接返回 false
  2. 如果两个字符串能够构成互相重排,那么每个字符串中各个字符出现的次数⼀定是相同的。因此,我们可以分别统计出这两个字符串中各个字符出现的次数,然后逐个⽐较是否相等即可。这样的话就可以选择哈希表来统计字符串中字符出现的次数。
  3. 该题字符都是小写字母,可用数组模拟哈希表(适合数据量小且集中),降低空间复杂度
cpp 复制代码
class Solution {
public:
    bool CheckPermutation(string s1, string s2) {
        if(s1.size()!=s2.size()) return false;
        int hash[26]={0};
        for(auto s:s1) hash[s-'a']++;
        for(auto s:s2) hash[s-'a']--;
        for(int i=0;i<26;i++) if(hash[i]!=0) return false;
        return true;
    }
};

三. (217.) 存在重复元素

算法原理:

题目至少出现两次的意思就是数组中存在重复元素,不需要计算元素出现次数只需查找当前元素在之前是否出现过即可,与两数之和思想一样。

可以使用哈希表,存储元素出现次数即可,一遍检查哈希表是否出现过当前元素,一边将(之前没出现过的)当前元素加入哈希表中

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;
    }
};

四. (219.) 存在重复元素 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;
            else hash[nums[i]]=i;
        }
        return false;
    }
};

五. (49.) 字⺟异位词分组

算法原理:

互为字⺟异位词的单词有⼀个特点:将它们「排序」之后,两个单词应该是完全相同的。

所以,我们可以利⽤这个特性,将单词按照字典序排序,如果排序后的单词相同的话,就划分到同⼀组中。这时我们就要处理两个问题:

• 排序后的单词与原单词需要能互相映射;

• 将排序后相同的单词,划分到同⼀组;

可以利用哈希表特性,key为排序后的字符串,value为string数组来存储所有异位词,这样就能处理每一个字符串不会重复添加,因为排序后的字符串都作为key值当索引,去找到对应的异位词数组添加原始字符串即可

cpp 复制代码
class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string,vector<string>>hash;
        //1.将字符串分组放入哈希表
        for(auto str:strs)
        {
            string tmp=str;
            sort(tmp.begin(),tmp.end());
            hash[tmp].push_back(str);
        }
        //2.将哈希表中value值取出当返回结果
        vector<vector<string>>ret;
        for(auto [x,y]:hash)
        {
            ret.push_back(y);
        }
        return ret;
    }
};
相关推荐
blasit5 小时前
笔记:Qt C++建立子线程做一个socket TCP常连接通信
c++·qt·tcp/ip
AI软著研究员5 小时前
程序员必看:软著不是“面子工程”,是代码的“法律保险”
算法
FunnySaltyFish5 小时前
什么?Compose 把 GapBuffer 换成了 LinkBuffer?
算法·kotlin·android jetpack
颜酱6 小时前
理解二叉树最近公共祖先(LCA):从基础到变种解析
javascript·后端·算法
地平线开发者1 天前
SparseDrive 模型导出与性能优化实战
算法·自动驾驶
董董灿是个攻城狮1 天前
大模型连载2:初步认识 tokenizer 的过程
算法
地平线开发者1 天前
地平线 VP 接口工程实践(一):hbVPRoiResize 接口功能、使用约束与典型问题总结
算法·自动驾驶
罗西的思考1 天前
AI Agent框架探秘:拆解 OpenHands(10)--- Runtime
人工智能·算法·机器学习
HXhlx1 天前
CART决策树基本原理
算法·机器学习
Wect1 天前
LeetCode 210. 课程表 II 题解:Kahn算法+DFS 双解法精讲
前端·算法·typescript