Day6 哈希表
当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。
但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。
LeetCode 242. 有效的字母异位词【哈希表/桶排序】
这题与其说是哈希表,更应该说是一种桶排序的思想,字母异位词换句话说就是两个字符串的每一种字母的个数都相同,所以我们用一个数组存两个字符串各个字母的个数,一个加,一个减,最后如果桶数组全为0就满足条件了。
class Solution {
public:
bool isAnagram(string s, string t) {
if(s.size()!=t.size()) return false;
int cnt[26];
memset(cnt,0,sizeof cnt);
for(int i=0;i<s.size();i++){
cnt[s[i]-97]++;
cnt[t[i]-97]--;
}
for(int i=0;i<26;i++)
if(cnt[i]) return false;
return true;
}
};
LeetCode 349. 两个数组的交集【哈希表】
本题用set来解决问题,主要看中了set的去重特性,同时了解一下set的查询机制。
set在查询不到元素时会返回表尾的迭代器,所以判断set中元素存在的条件是nums.find(num)!=nums.end()
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> res;
unordered_set<int> nums(nums1.begin(),nums1.end());
for(int num:nums2)
if(nums.find(num)!=nums.end())
res.insert(num);
return vector<int>(res.begin(),res.end());
}
};
LeetCode 202.快乐数【哈希表】
数快不快乐我不知道,我不快乐了。
代码随想录里点明了困扰我的点,如何判断对这个数的额操作会一直进行下去?那就是之前出现过的数还会再次出现。由这一点判断要使用哈希表。实在是令人大呼佩服。
class Solution {
public:
int getSum(int n){
int sum=0;
while(n){
sum+=(n%10)*(n%10);
n/=10;
}
return sum;
}
bool isHappy(int n) {
unordered_set<int> s;
while(1){
int sum=getSum(n);
if(sum==1) return true;
if(s.find(sum)!=s.end()) return false;
else s.insert(sum);
n=sum;
}
}
};
LeetCode 1.两数之和【暴力/哈希表】
第一题,两数之和,为什么不是a+b呢??
无所谓,我们会暴力。
解法1:暴力
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int n=nums.size();
for(int i=0;i<n;i++) {
for(int j=i+1;j<n;j++){
if(nums[i]+nums[j]==target){
return {i,j};
}
}
}
return {};
}
};
解法2:哈希表
纳尼?还有高手?
因为本题既需要存储值,还要找到对应的下标,所以我们想到用map来存储已经遍历过的元素,当我们再向后遍历数组时,再在map中寻找有没有它的另一半target-nums[i],如果找到了,就返回他和他另一半的下标。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> map;
for(int i=0;i<nums.size();i++){
auto iter=map.find(target-nums[i]);
if(iter!=map.end())
return {iter->second,i};
map.insert(pair<int,int>(nums[i],i));
}
return {};
}
};
哈希表本身并不算难理解,难在你如何想到要用哈希表来解决问题,除此之外,合理根据题目条件选择合适的哈希数据结构也是关键的一环。