【算法系列】哈希表

news2024/10/7 4:27:09

目录

哈希表总结

leetcode题目

一、两数之和

二、判定是否互为字符重排

三、存在重复元素

四、存在重复元素 II

五、字母异位词分组

六、在长度2N的数组中找出重复N次的元素

七、两个数组的交集

八、两个数组的交集 II

九、两句话中的不常见单词


哈希表总结

1.存储数据的容器

2.需要快速查找数据时,用哈希表

3.当题目中给定的字符串或者数组只包含小写字母或数据范围是0~100/1000等等时,可以用数组模拟哈希表

4.当数据范围是负数到正数时,不建议用数组模拟哈希表,因为还要加一个数转化之后进行映射,建议直接使用STL容器

leetcode题目

一、两数之和

1. 两数之和 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/two-sum/1.题目解析

给定数组与target, 返回和为target的两个元素下标

2.算法分析

解法一: 暴力枚举

策略一: 先固定一个数,然后依次与该数之后的数相加

策略二: 先固定一个数,然后依次与该数之前的数相加

解法二: 使用哈希表优化

暴力解法之所以慢,以策略二为例,  是因为枚举到nums[i]时,要在这个位置之前都遍历一下,看哪个数字等于target-nums[i], 所以如果我们枚举到nums[i]时,前面的数字都被扔进了哈希表中,我们就可以以O(1)的时间复杂度找到结果~

注意:如果是用哈希表暴力枚举策略一,最好是倒着遍历~

3.算法代

暴力枚举策略一:

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

暴力枚举策略二:

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

哈希表优化策略一:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) 
    {
        unordered_map<int, int> hash; //<nums[i], i>
        for(int i = nums.size()-1; i >= 0; i--)
        {
            int x = target - nums[i];
            if(hash.count(x)) 
                return {hash[x], i};
            hash[nums[i]] = i;
        }
        return {-1, -1}; //照顾编译器
    } 
};

哈希表优化策略二:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) 
    {
        unordered_map<int, int> hash; //<nums[i], i>
        for(int i = 0; i < nums.size(); i++)
        {
            int x = target - nums[i];
            if(hash.count(x)) 
                return {hash[x], i};
            hash[nums[i]] = i;
        }
        return {-1, -1}; //照顾编译器
    } 
};

二、判定是否互为字符重排

面试题 01.02. 判定是否互为字符重排 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/check-permutation-lcci/1.题目解析

给定两个字符串,判断一个字符串是否能够通过重排变成另一个字符串

2.算法分析

如果s1能够重排形成s2,  那么s1每个字符出现的个数和s2对应字符出现的个数是相等的!于是可以使用哈希表,而题目中说字符串只有小写字母,因此用数组模拟哈希表即可。所以解法就是用两个哈希表,然后判断哈希表是否相等即可;

优化1: 只使用一个哈希表统计s1中字符个数,然后遍历第二个字符串,把对应字符在哈希表中的个数--, 如果--之后是负数了,返回false即可

优化2: 两个字符串的长度不相等,直接返回false即可

3.算法代码

class Solution {
public:
    bool CheckPermutation(string s1, string s2)
    {
        //优化
        if(s1.size() != s2.size()) 
            return false;
            
        int hash[26] = {0};
        for(auto& e : s1)   
            hash[e - 'a']++;
        for(auto& e : s2)
        {
            hash[e - 'a']--;
            if(hash[e - 'a'] < 0)
                return false;
        }
        return true;
    }
};

三、存在重复元素

217. 存在重复元素 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/contains-duplicate/1.题目解析

数组中存在重复元素返回true, 不存在重复元素返回false

2.算法分析

使用哈希表解决问题~

3.算法代码

unordered_map:

class Solution {
public:
    bool containsDuplicate(vector<int>& nums) 
    {
        unordered_map<int, int> hash;
        for(auto& e : nums)
        {
            hash[e]++;
            if(hash[e] > 1) 
                return true;
        }
        return false;
    }
};

unordered_set: 

class Solution {
public:
    bool containsDuplicate(vector<int>& nums) 
    {
        unordered_set<int> hash;
        for(auto& e : nums)
        {
            if(hash.count(e)) 
                return true;
            else
                hash.insert(e);
        }
        return false;
    }
};

四、存在重复元素 II

219. 存在重复元素 II - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/contains-duplicate-ii/1.题目解析

判断数组中是否存在两个相同的元素,并且下标的绝对值小于等于k

2.算法分析

从前向后遍历数组,同时将遍历过的元素和下标绑定扔进哈希表,遍历的同时判断是否满足题意即可

小细节:nums = [1 0 2 1 3 1 4],  k =2,   当遍历到第2个1时,发现下标i-j=3>k, 不满足题意,此时将1和下标3绑定扔进哈希表覆盖之前的 <1, 0> 是完全可以的, 因为题目求的是 i-j <= k, 因此i和j越近越好,因此我们可以直接覆盖原先的值~

3.算法代码

class Solution {
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) 
    {
        unordered_map<int, int> hash; // <nums[i], i>
        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;
    }
};

五、字母异位词分组

49. 字母异位词分组 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/group-anagrams/description/1.题目解析

给一个字符串数组,将所有的字母异位词放到一组,返回一个二维数组

2.算法分析

1.判断两个字符串是否是字母异位词(可以用哈希表,但是代码不好写,我们选择直接排序, 排序结果一样,那就互为字母异位词)

2.将相同的字母异位词分组 --- 借助哈希表 <string, string[ ]>, 哈希表第一个位置存储排序后的字符串,第二个存储一个字符串数组;

3.算法代码

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) 
    {
        unordered_map<string, vector<string>> hash;
        //1.将所有的字母异位词分组
        for(auto& s : strs)
        {
            string tmp = s;
            sort(tmp.begin(), tmp.end());
            hash[tmp].push_back(s);
        }
        //2.提取结果
        vector<vector<string>> ret;
        for(auto& [x, y] : hash)
        {
            ret.push_back(y);
        }
        return ret;
    }
};

六、在长度2N的数组中找出重复N次的元素

961. 在长度 2N 的数组中找出重复 N 次的元素 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/n-repeated-element-in-size-2n-array/description/1.题目解析

我们在深剖一下题意,本质就是只有1个数重复出现了,其他数都只出现了一次

2.算法分析

思路一: 遍历数组,将当前元素和出现次数丢进哈希表,当某个数出现次数 == n时,返回该数

思路二: 遍历数组,进循环先判断该数是否已经存在,存在就直接返回,不存在就将该数丢进哈希表

3.算法代码

思路一:

class Solution {  
public:  
    int repeatedNTimes(vector<int>& nums)  
    {  
        size_t n = nums.size() / 2;
        unordered_map<int, int> hash; // [x, count]  
        for(auto& e : nums)  
        {  
            hash[e]++;  
            if(hash[e] == n)   
                return e;  
        }  
        return -1;
    }  
};

思路二:

class Solution {  
public:  
    int repeatedNTimes(vector<int>& nums)  
    {  
        unordered_map<int, int> hash; // [x, count]  
        for(auto& e : nums)  
        {  
            if(hash[e] == 1) // 只需要检查是否已经存在(即重复了一次)  
                return e;  
            hash[e]++;  
        }  
        return -1;
    }  
};

七、两个数组的交集

349. 两个数组的交集 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/intersection-of-two-arrays/submissions/

1.题目解析

返回两个数组的交集(输出结果的每个元素要是唯一的)

2.算法分析

将两个数组元素扔进两个 unordered_set 哈希表进行去重,然后遍历其中一个哈希表,看该哈希表中的元素在另一个哈希表中是否存在,存在就插入到结果数组中!

3.算法代码

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) 
    {
        vector<int> ret;
        unordered_set<int> hash1;
        unordered_set<int> hash2;
        for(auto& e : nums1) //对nums1元素去重
            hash1.insert(e);
        for(auto& e : nums2) //对nums2元素去重
            hash2.insert(e);

        for(auto& e : hash1)
            if(hash2.count(e))
                ret.push_back(e);
        return ret;
    }
};

八、两个数组的交集 II

350. 两个数组的交集 II - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/intersection-of-two-arrays-ii/1.题目解析

返回两个数组的交集 (结果中可以有重复元素)

2.算法分析

定义一个哈希表 unordered_map,遍历第一个数组,将 数组元素和出现的个数绑定扔进哈希表, 然后遍历第二个数组,元素在哈希表中出现,就插入到结果数组中,然后将该元素在哈希表中的个数--即可

3.算法代码

class Solution {
public:
    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) 
    {
        unordered_map<int, int> hash;
        for(auto& e : nums1)
            hash[e]++;

        vector<int> ret;
        for(auto& e : nums2)
        {
            if(hash[e])
            {
                ret.push_back(e);
                hash[e]--;
            }
        }
        return ret;
    }
};

九、两句话中的不常见单词

884. 两句话中的不常见单词 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/uncommon-words-from-two-sentences/description/

1.题目解析

返回两句话中互相在另一句话中没有出现的所有单词

2.算法分析

可以将两个字符串合在一起,提取出所有的单词同时扔进哈希表统计单词出现的次数,然后遍历一遍哈希表,出现次数为1的单词就是我们要的结果

3.算法代码

class Solution {
public:
    vector<string> uncommonFromSentences(string s1, string s2) 
    {
        //1.将所有的单词提取出来
        vector<string> words;
        string tmp;
        string s = s1 + ' ' + s2;
        unordered_map<string, int> hash;
        for(size_t i = 0; i <= s.size(); i++)
        {
            if(s[i] != ' ' && i != s.size())
                tmp += s[i];
            else
            {
                words.push_back(tmp);
                hash[tmp]++;
                tmp.clear();
            }
        }

        //2.从哈希表中提取结果
        vector<string> ret;
        for(auto [x, y] : hash)
            if(y == 1)
                ret.push_back(x);
        return ret;
    }
};

十、字符串中的第一个唯一字符

387. 字符串中的第一个唯一字符 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/first-unique-character-in-a-string/

1.题目解析

找字符串中第一个只出现一次的字符

2.算法分析

数组模拟哈希表,遍历字符串s,统计出每个字符出现的次数,然后再遍历一遍哈希表,找出出现次数为1的字符,返回下标

3.算法代码

class Solution {
public:
    int firstUniqChar(string s) 
    {
        int hash[26] = {0};
        for(auto& e : s)
            hash[e-'a']++;
        for(int i = 0; i < s.size(); i++)
            if(hash[s[i]-'a'] == 1)
                return i;
        return -1;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1642314.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

登封授牌,花落郑州

近日&#xff0c;“大禹故里故都”授牌仪式在河南省登封市隆重举行&#xff0c;河南省社科院有关单位将匾牌授予登封市。报道称&#xff1a;至此&#xff0c;千百年来备受争议的大禹故里、故都问题&#xff0c;终于尘埃落定&#xff0c;华夏立国始祖大禹终于魂归故里。 略有微词…

《尿不湿级》STM32 F103C8T6最小系统板搭建(五)BOOT

一、BOOT是什么&#xff1f; 大多数初学者第一次接触BOOT总是对这个词感到不解&#xff0c;从哪冒出一个奇奇怪怪的东西还要接跳线帽&#xff0c;为什么要配置它才能进行串口程序的下载&#xff1f;为什么不正确配置会导致单片机无法正常启动…… boot&#xff0c;及物动词&…

IP 地理定位神话与事实

ip地理定位是一项技术&#xff0c;用于通过访问设备的ip地址来获取地理位置信息&#xff0c;例如国家、城市、经纬度等。该技术广泛应用于网站内容自定义、广告定位、网络安全和用户分析等领域。它通过与包含ip地址和地理位置映射的大型数据库进行查询来工作&#xff0c;但在准…

LeetCode406:根据身高重建队列

题目描述 假设有打乱顺序的一群人站成一个队列&#xff0c;数组 people 表示队列中一些人的属性&#xff08;不一定按顺序&#xff09;。每个 people[i] [hi, ki] 表示第 i 个人的身高为 hi &#xff0c;前面 正好 有 ki 个身高大于或等于 hi 的人。 请你重新构造并返回输入数…

「JavaEE」线程安全2:内存可见性问题 wait、notify

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;JavaEE &#x1f387;欢迎点赞收藏加关注哦&#xff01; 内存可见性问题& wait、notify &#x1f349;Java 标准库的线程安全类&#x1f349;内存可见性问题&#x1f34c;volatile 关键字 …

python大数据项目中的 DIM层数据处理

一、处理维度表数据 hive的配置 -- 开启动态分区方案 -- 开启非严格模式 set hive.exec.dynamic.partition.modenonstrict; -- 开启动态分区支持(默认true) set hive.exec.dynamic.partitiontrue; -- 设置各个节点生成动态分区的最大数量: 默认为100个 (一般在生产环境中, 都…

步进电机与伺服电机的区别

什么是电机&#xff1f; 电机是一种将电能转换为机械能的装置&#xff0c;通常由定子、转子和电磁场组成。当电流通过电机的绕组时&#xff0c;产生的磁场会与电机中的磁场相互作用&#xff0c;从而使电机产生旋转运动。电机广泛应用于各种机械设备和工业生产中&#xff0c;是现…

5.4代码

1.本质上升序列 我想到的是用回溯去找子集一个一个判断&#xff0c;当然这样的话会来的很慢&#xff0c;然后就在网上找到了大佬的方法&#xff0c;这东西居然是用动态规划来的&#xff0c;说是最长递增子序列的类似问题 &#xff0c;感觉我好像写过类似的&#xff0c;但是去找…

gitee关联picgo设置自己的typora_图床

一&#xff1a;去gitee官网创建仓库&#xff1a;typora_图床 1.百度搜索关键字&#xff1a;gitee&#xff0c;进入官网 2.进入gitee登录或者注册自己的账号 3.进入主页后&#xff0c;点击右上方 4.点击新建仓库 5.设置仓库名&#xff1a;typora_图床 6.点击5的创建&#xff0…

基于Springboot的校运会管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的校运会管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&a…

让我们一起来领悟带环问题的核心思想

一、带环的链表&#xff1a; 本质还是快慢指针来解决 关于如下一个带环链表怎么去找到他们想碰到的节点呢&#xff1f;&#xff1f;&#xff1f;&#xff1f;我们可以想到快慢指针&#xff0c;第一个快点走&#xff0c;若是有环就会进入环&#xff0c;此时快指针每次走2步&am…

边缘计算含义与应用简析

边缘计算概述 边缘计算使数据存储和处理靠近生成或收集数据的位置&#xff0c;而不是在位于数千公里的服务器上。它将通过保持灵活性在边缘无缝可靠地部署服务。它比云计算更安全&#xff0c;因为不需要传输数据。因此&#xff0c;在将数据从边缘移动到云端时&#xff0c;不用…

嵌入式开发六:新建工程—寄存器版

通过前面的学习&#xff0c;我们对 STM32 有了个比较清晰的了解&#xff0c;本次我们将讲解新建寄存器库版本 MDK 工程的详细步骤。后期我们基于固件库开发&#xff0c;借助Keil5的环境配置助手界面RTE&#xff0c;不需要进行文件移植&#xff0c;本节的寄存器版本&#xff0c;…

测试通过!X-Argus、X-Gorgon、X-Medusa和X-Helions

算法分析测试 Host:api5-normal-sinfonlinea.fqnovel.com Cookie:install_id2821771262445211; ttreq1$eb27d336c987581d9ed1b36c48cab2c7bcbc7305; d_ticket38b3fb964c1b4c5955565dc0f91cfcf64df74; odin_tte25761a2638b499c0bf8840c9857e43a17899df1213ba33153a266bbddf47b5…

CSS盒子模型 (盒子模型 下)

&#xff08;大家好&#xff0c;今天我们将继续来学习CSS的相关知识&#xff0c;大家可以在评论区进行互动答疑哦~加油&#xff01;&#x1f495;&#xff09; 目录 1.4 表格的细线边框 1.5 边框会影响盒子实际大小 1.6 内边距(padding) 案例&#xff1a;新浪微博选框栏…

口才训练:如何用声音和语言展现自我魅力

口才训练&#xff1a;如何用声音和语言展现自我魅力 这里有一篇1270字左右的文章&#xff0c;主要介绍如何用声音和语言来展现自我魅力&#xff1a; 口才训练是提升个人魅力的重要途径之一。魅力不仅取决于外表&#xff0c;更重要的是声音和语言的运用。良好的语言表达能力可以…

CMakeLists.txt语法规则:部分常用命令说明一

一. 简介 前一篇文章简单介绍了CMakeLists.txt 简单的语法。文章如下&#xff1a; CMakeLists.txt 简单的语法介绍-CSDN博客 接下来对 CMakeLists.txt语法规则进行具体的学习。本文具体学习 CMakeLists.txt语法规则中常用的命令。 二. CMakeLists.txt语法规则&#xff1a;…

小程序账号设置以及request请求的封装

一般开发在小程序时&#xff0c;都会有测试版和正式版&#xff0c;这样在开发时会比较方便。 在开发时。产品经理都会给到测试账号和正式账号&#xff0c;后端给的接口也都会有测试环境用到的接口和正式环境用到的接口。 这里讲一讲我这边如何去做的。 1.在更目录随便命名一…

Ubuntu20安装torch1.13和pytorch_geometric2.3.0(对应cuda11.6)

在torch下载页面搜索1.13https://pytorch.org/get-started/previous-versions/&#xff0c;wheel安装方式&#xff08;激活conda虚拟环境&#xff09; pip install torch1.13.0cu116 torchvision0.14.0cu116 torchaudio0.13.0 --extra-index-url https://download.pytorch.org…

“100先生”逢跌加仓

原创 | 刘教链 BTC&#xff08;比特币&#xff09;从前日创下的局部低点56.5k持续修复至59k上方&#xff0c;距离重回6万刀仅有半步之遥。 群里有群友还在等25k。还有朋友发来消息问&#xff0c;这次是不是有机会跌回15k&#xff1f; 躺下睡一觉。梦里会有的。 就在前两天ETF们…