【算法】哈希表专题
一. (1.) 两数之和
算法原理:
1.暴力解法:从前往后
用两遍for循环,固定一个数,在这个数之前遍历看是否相加等于目标值,正反遍历都可以,但哈希表优化是基于反向遍历的
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,哈希表是以空间换时间的策略
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.) 判定是否互为字符重排
算法思路:
- 当两个字符串的⻓度不相等的时候,是不可能构成互相重排的,直接返回 false
- 如果两个字符串能够构成互相重排,那么每个字符串中各个字符出现的次数⼀定是相同的。因此,我们可以分别统计出这两个字符串中各个字符出现的次数,然后逐个⽐较是否相等即可。这样的话就可以选择哈希表来统计字符串中字符出现的次数。
- 该题字符都是小写字母,可用数组模拟哈希表(适合数据量小且集中),降低空间复杂度
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.) 存在重复元素
算法原理:
题目至少出现两次的意思就是数组中存在重复元素,不需要计算元素出现次数只需查找当前元素在之前是否出现过即可,与两数之和思想一样。
可以使用哈希表,存储元素出现次数即可,一遍检查哈希表是否出现过当前元素,一边将(之前没出现过的)当前元素加入哈希表中
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
算法原理:
与两数之和思想一样,利用哈希表,将元素值和下标绑定存入其中,在找当前元素之前是否重复出现元素同时判断其下标相减是否符合要求。
注意当出现重复元素放入哈希表中会产生覆盖,这里允许覆盖因为题目要求下标差值为<=,由于是从左往右遍历,先入哈希表的重复数据被覆盖不会有影响因为先入的能符合题意,后重复的元素一定符合题意,反之就不行。
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值当索引,去找到对应的异位词数组添加原始字符串即可
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;}
};