C++算法学习专题:哈希算法
本篇内容我们就来学习一下算法界的一个经典算法思想:哈希算法
目录
什么是哈希表和哈希算法?
哈希算法有什么用?
什么时候用哈希算法?
怎么用哈希算法?
1、两数之和
2、判断是否为字符重排
3、出现重复元素
4、出现重复元素2
5、字母异位词分组
什么是哈希表和哈希算法?
哈希表就是一个存储数据的容器。
哈希算法(Hash Algorithm)是一种将任意长度的数据映射为固定长度值的单向加密函数。它通过特定的数学运算,将输入(也称为"消息")转换为一个固定长度的字符串(通常为十六进制表示),这个字符串称为哈希值或摘要。
哈希算法具有以下核心特性:
- 确定性:相同的输入总是产生相同的输出
- 快速计算:对于给定数据,可以快速计算出哈希值
- 不可逆性:从哈希值无法反推出原始数据
- 抗碰撞性:很难找到两个不同的输入产生相同的哈希值
- 雪崩效应:输入数据的微小变化会导致输出哈希值的巨大差异
哈希算法有什么用?
“快速”查找某个元素(时间复杂度O(1))
什么时候用哈希算法?
当我们需要频繁地查找某一个数据的时候可以用哈希算法。
同时二分算法也可以,不过受限于排序
但是哈希算法对于空间的损耗特别大。
怎么用哈希算法?
任何高级语言都有哈希表这个容器(C语言没有)
1、容器(哈希表)
2、用数组模拟简易的哈希表。
哈希相关的资料可以参考文档:
<unordered_map> - C++参考
<unordered_set> - C++参考
1、两数之和
解法一:暴力枚举
1、先固定一个数字
2、依次与该数之前的数相加
解法二:用哈希算法优化
class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {//老版本写法:暴力解法// int left=0,right=nums.size()-1;// vector<int>arr=nums;// sort(arr.begin(),arr.end());// while(left<right)// {// int sum=arr[left]+arr[right];// if(sum==target) // {// break;// }// else if(sum<target) // {// ++left; // }// else if(sum>target)// {// --right; // } // }// int x = arr[left], y = arr[right];// left = right = -1;// for (int k = 0; k < nums.size(); ++k) // {// if (nums[k] == x && left== -1)// left = k;// if (nums[k] == y)// right = k;// }// return { left, right };//新版本写法:哈希表、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};else{hash[nums[i]]=i;}}return {-1,-1};//返回无效下标}
};
2、判断是否为字符重排
解法思路:
1、建立两个哈希表,分别用于统计字符出现的个数
优化:使用一个哈希表,统计s1,遍历s2的时候相同字符均减去1,若为0则相等,反之不等
2、用数组模拟哈希表。
时间复杂度O(n)
class Solution {
public:bool CheckPermutation(string s1, string s2) {if(s1.size()!=s2.size()){return false;}int hash[26]={0};//统计s1的信息for(auto ch:s1){//利用'a'映射的下标为0hash[ch-'a']++;}//扫描第二个字符串for(auto ch:s2){hash[ch-'a']--;if(hash[ch-'a']<0){return false;}}return true;}
};
3、出现重复元素
答案:
class Solution {
public:bool containsDuplicate(vector<int>& nums){unordered_set<int>hash;for(auto x:nums){if(hash.count(x)) return true;else hash.insert(x);} return false;}
};
4、出现重复元素2
答案:
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])){if((i-hash[nums[i]])<=k) return true;}hash[nums[i]]=i;} return false;}
};
5、字母异位词分组
解题思路:
1、排序
2、分组:
答案:
class Solution {
public:vector<vector<string>> groupAnagrams(vector<string>& strs) {unordered_map<string,vector<string>>hash;//将所有字母异位词分组for(auto x:strs){string tmp=x;sort(tmp.begin(),tmp.end());hash[tmp].push_back(x);}//将结果提炼出来vector<vector<string>> ret;//我们要的是y值for(auto& [x,y]:hash){ret.push_back(y);}return ret;}
};
本期的内容先到这里,作者后续还会进一步地深入学习哈希表及其哈希算法
喜欢请点个赞谢谢