哈希法常用的三种数据结构:数组、set、map。
当哈希值较小,范围较小可控时,用数组;当数值很大,使用set;当存在k及对应value时,使用map。
什么时候想到用哈希法?判断一个元素是否出现的时候。
LeetCode 242.有效的字母异位词
字母异位词:指两字符串长度相同,字母相同,位置不同。
t 是 s 的异位词等价于「两个字符串排序后相等」。
class Solution {
public:
bool isAnagram(string s, string t) {
//定义一个数组,存储每个字母出现的次数
int hash[26] = {0};
// for(int i = 0;i < 26;i++){
// hash[i] = 0;
// }
//s[i]-'a'计算出对应字母的下标,如第一个字母时a时,s[0]-'a' = 0
for(int i =0;i < s.size();i++){
hash[s[i]-'a']++;
}
//对于t中的字母,没出现一次,进行一次--操作
for(int i = 0;i < t.size();i++){
hash[t[i]-'a']--;
}
//看数组中哪个下表对应的元素不为0;如果大于0,说明该字母s中出现次数多于t;小于0,说明t中出现次数多余s
for(int i = 0;i < 26;i++){
if(hash[i] != 0){
return false;
}
}
return true;
}
};
LeetCode349. 两个数组的交集
1.使用unordered_set形式的哈希结构
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
//存放结果的集合,由于结果中每个元素是唯一的,而unordered_set具有去重的功能
unordered_set<int>result_set;
//选择unorder_set结构存储nums2,即将nums2放入哈希表
//初始化;
unordered_set<int>nums_set(nums2.begin(),nums2.end());
for(int num : nums1){
// find函数查找元素是否存在,若存在,返回指向该值的迭代器;若不存在,返回set.end()
if(nums_set.find(num) != nums_set.end()){
result_set.insert(num);
}
}
//返回一个数组形式,!!!要注意返回值类型是vector
return vector<int>(result_set.begin(),result_set.end());
}
};
2.使用数组作为哈希法的数据结构
(1)这里将使用hash数组存储nums1中的元素,并标记其状态存在(1)或者不存在(0),将数组nums1中的元素作为索引。
(2)判断相同的数的逻辑:如果两个数相同,那么nums2中的值也作为hash数组中的一个索引,在hash数组中能够找到对应索引的值,且值为1。
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int>result_set; //存放结果
int hash[1002] = {0};
//这里将使用hash数组存储nums1中的元素,并标记其状态存在(1)或者不存在(0),将数组nums1中的元素作为索引。
for(int i = 0;i < nums1.size();i++){
hash[nums1[i]]=1;
}
//判断相同的数的逻辑:如果两个数相同,那么nums2中的值也作为hash数组中的一个索引,在hash数组中能够找到对应索引的值,且值为1.
for(int num : nums2){
if(hash[num] == 1){
result_set.insert(num);
}
}
return vector<int>(result_set.begin(),result_set.end());
}
};
LeetCode 202. 快乐数
「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为 1,那么这个数就是快乐数。
取一个正整数n每个的数:
(1)取余:n % 10 取得个位上的数
(2)取商:n /=10 去掉最末尾的数(即去掉个位上的值)
一直重复,可以获得每个位置上的数。
class Solution {
public:
//计算n的每个位置上的数的平方和
int getSum(int n){
int sum = 0;
while(n){
int digit = n % 10; //取余
sum += digit*digit;
n /= 10; //取商
}
return sum;
}
bool isHappy(int n) {
//判段这个数是否重复出现
unordered_set<int>set;
while(1){
int sum = getSum(n);
if(sum == 1){
return true;
}
//在set中查找是否有相同的元素
if(set.find(sum) != set.end()){
return false;
}
else{
set.insert(sum);
}
n = sum;
}
}
};
LeetCode 1. 两数之和
利用unordered_map接收数据
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
//将未匹配上的值存放
unordered_map<int,int>m;
for(int i = 0;i < nums.size(); i++){
//定义一个指针接收find的返回值
unordered_map<int,int>::iterator it = m.find(target-nums[i]);
//如果可以找到对应的值,返回数据元素和对应下标
if(it != m.end()){
return{it->second,i};
}
//否则,将数据添加到m中
else{
m.insert(pair<int,int>(nums[i],i));
}
}
//如果都没找到,返回空
return {};
}
};