相关链接
视频讲解:学透哈希表,数组使用有技巧!Leetcode:242.有效的字母异位词_哔哩哔哩_bilibili
视频讲解:学透哈希表,set使用有技巧!Leetcode:349. 两个数组的交集_哔哩哔哩_bilibili
视频讲解:梦开始的地方,Leetcode:1.两数之和,学透哈希表,map使用有技巧!_哔哩哔哩_bilibili
有效字母的异位词
解题思路
本题字符串s和t都是小写字母,我们知道a-z是连续的,可以开辟一个数组表示这26个字母出现的次数,初始值都为0。遍历s,出现的字母在对应的数组下标位置的值进行自增,表示出现一次。遍历t,进行自减操作。若数组的最后的值都为0,表示字母出现的次数相等则符合题意。
AC代码
class Solution {
public:
bool isAnagram(string s, string t) {
int p[26]={0};
for(int i=0;i<s.size();i++)
{
p[s[i]-'a']++;
}
for(int i=0;i<t.size();i++)
{
p[t[i]-'a']--;
}
for(int i=0;i<26;i++)
{
if(p[i]!=0)
return false;
}
return true;
}
};
两个数组的交集
解题思路-用set解决
原先力扣没有对数据进行相关限制,在这种数据情况下选用set更为合适,因为可能数据很大,数组一般情况下数据范围较小。
当我们要使用集合来解决哈希问题的时候,优先使用unordered_set,因为它的查询和增删效率是最优的,如果需要集合是有序的,那么就用set,如果要求不仅有序还要有重复数据的话,那么就用multiset。
根据题意,最后的数组是经过去重的,所以选用unordered_set解决此问题。建立一个集合存放最终的数据还有一个集合是对nums1的数据进行映射,然后对nums2进行判断,若nums2中的数字在该集合中可以查找则对结果集合进行添加的操作。
AC代码
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int>result_set;
unordered_set<int>num_set(nums1.begin(),nums1.end());
int num;
for(int i=0;i<nums2.size();i++)
{
num=nums2[i];
if(num_set.find(num)!=result_set.end())
result_set.insert(num);
}
return vector<int>(result_set.begin(),result_set.end());
}
};
解题思路-用数组解决
AC代码
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
int hash[1005]={0};
unordered_set<int>result_set(1005);
for(int i=0;i<nums1.size();i++)
{
hash[nums1[i]]=1;
}
for(int i=0;i<nums2.size();i++)
{
if(hash[nums2[i]]==1)
{
result_set.insert(nums2[i]);
}
}
return vector<int>(result_set.begin(), result_set.end());
}
};
快乐数
解题思路
首先创建一个函数求得一个数经过一次替换后的sum值,之后循环的时候直接进行调用。将每次求得的sum映射到unordered_set型的集合中,因为一旦发现sum值有重复则表示进入循环,直接返回false。
AC代码
class Solution {
public:
int getSum(int n){
int sum=0;
while(n)
{
sum+=(n%10)*(n%10);
n=n/10;
}
return sum;
}
bool isHappy(int n) {
unordered_set<int>result_set;
while(1)
{
int sum=getSum(n);
if(sum==1)
return true;
if(result_set.find(sum)!=result_set.end())
{
return false;
}
else
{
result_set.insert(sum);
}
n=sum;
}
}
};
遇到的难题&&总结
这道题的循环过程有点混乱,之后复盘的时候再过一遍。还有一个注意点,附上相关链接。
这是标准库里迭代器部分的内容,简单点说,就是用find这个函数,去找str这个序列中的i元素,如果序列中所找的这个元素不存在,就会返回end()。
那么按着这个思路去理解这两行命令就很容易了!
如果str.find(i)返回的不是str.end(),就说明在str序列中找到i元素:
str.find(i) != str.end() //说明找到了
同理,如果str.find(i)返回的是str.end(),就说明在str序列中没找到i元素: str.find(i) == str.end() //说明没到
这个地方跟正常的理解逻辑相反,注意区分。
————————————————
版权声明:本文为CSDN博主「恋蛩音」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_17846375/article/details/104814813
两数之和
解题思路
遍历数组的时候,只需要向map去查询是否有和目前遍历元素匹配的数值,如果有,就找到的匹配对,如果没有,就把目前遍历的元素放进map中,因为map存放的就是我们访问过的元素。若已经遍历过的数值和此时数组中值相加为目标值则返回此时它们的下标。
什么时候使用哈希法,当我们需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要第一时间想到哈希法。
1)使用哈希法的原因:需要一个集合来存放我们遍历过的元素,然后在遍历数组的时候去询问这个集合,某元素是否遍历过,也就是是否出现在这个集合。
2)们不仅要知道元素有没有遍历过,还要知道这个元素对应的下标,需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适。这道题目中并不需要key有序,选择std::unordered_map 效率更高!
3)map目的用来存放我们访问过的元素,因为遍历数组的时候,需要记录我们之前遍历过哪些元素和对应的下标,这样才能找到与当前元素相匹配的(也就是相加等于target)接下来是map中key和value分别表示什么。这道题 我们需要 给出一个元素,判断这个元素是否出现过,如果出现过,返回这个元素的下标。那么判断元素是否出现,这个元素就要作为key,所以数组中的元素作为key,有key对应的就是value,value用来存下标。
AC代码
lass Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
std::unordered_map<int,int>map;
for(int i=0;i<nums.size();i++)
{
auto index=map.find(target-nums[i]);
if(index!=map.end())
{
return{index->second,i};
}
map.insert(pair<int,int>(nums[i],i));
}
return {};
}
};
遇到的困难&&总结
第一次了解哈希这部分的算法,一些基础语法还不是很熟悉,之后看看STL这部分(怎么感觉总是在说之后,好像画大饼)