哈希表
常见的三种哈希结构:
1.数组(常见于对字符串的判断,将26个字母存储在数组中,对数组对应位置的值进行处理)
注意事项:1.如果题目给定的数据限制很大,则不能使用数组
2.集合 unordered_set,当要求查找重复元素或者条件要求的数据限制很大的时候使用
3.映射 unordered_map,当需要考虑元素的值和索引时,考虑使用hash map,通过键值对找到需要的元素key:数据元素,value:索引下标
思路由于本题的数据限制较小,因此可以考虑在哈希性质下用数组做,先将26个字母存储在数组中,然后将字符串s的所有字符存储到数组中,对应数组下标为0的地方存储'a',25的地方存储'z',然后将字符串t的字符对应相减,最后判断是否数组的所有元素和为0
代码:
class Solution {
public:
bool isAnagram(string s, string t) {
int record[26] = {0};//定义一个包含所有字母的数组,且每个单词出现的次数就是数组对应位置的数字
int nums = 0;
for(int i = 0;i < s.size();i++)
{
record[s[i] - 'a']++;//将s字符串出现的字母,在数组对应位置+1
}
for(int i = 0;i < t.size();i++)
{
record[t[i] - 'a']--;//将t字符串出现的字母,在数组对应位置-1
}
for(int i = 0;i < 26;i++)
{
nums += record[i];//判断是否此时数组中的所有元素之和是否为0,不为0则不是异位字符串
if(nums != 0) return false;
}
return true;
}
};
思路:
unordered_set:
解决类似的重复元素,都可以使用无序集合去重元素
数组:
当题目给定的数据限制不大时,使用数组的效率更高,
代码:
无序集合:
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> result;
unordered_set<int> nums_set(nums1.begin(),nums1.end());
for(int num : nums2)
{
if(nums_set.find(num) != nums_set.end())//如果nums_set中没找到nums的元素,就返回end,如果不等说明存在元素num
{
result.insert(num);
}
}
return vector<int>(result.begin(),result.end());
}
};
数组:
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
int hash[1001] = {0};//定义一个数组储存可能存在的所有出现的数字
unordered_set<int> arr;
for(int num : nums1)//便利nums1的所有数字
{
hash[num] = 1;//给对应的数字赋值
}
for(int num : nums2)
{
if(hash[num] == 1)//只要该数字在nums2也出现,就存储在无序集合
arr.insert(num);
}
return vector<int>(arr.begin(),arr.end());
}
};
思路:
1.首先定义求和函数get_sum,当n/10<1,即n成为个位数时,跳出循环
2.调用求和函数,并且用无序列表储存所有出现的和,直到最后出现和为1的时候返回true,或者出现过相同的元素,返回false
3.需要考虑可能出现死循环的情况,用unordered_set,判断当前的sum有没有出现过,如果find函数找到了,则立马返回false
代码:
class Solution {
public:
int get_nums(int n){
int sum = 0;
while(n)
{
sum += (n % 10) * (n % 10);
n = n / 10;
}
return sum;
}
bool isHappy(int n) {
unordered_set<int> set;
int s;
while(1)
{
s = get_nums(n);
if(s == 1) return true;
if(set.find(s) != set.end()) return false;
else set.insert(s);
n = s;
}
}
};
思路:
- 为什么会想到用哈希表
当面临需要查找元素是否出现或者与集合有关的时候,需要考虑哈希表
- 哈希表为什么用map
本题需要返回数据元素和下标,map可以存储键值对
- 本题map是用来存什么的
用来存储遍历过后的键值对,由元素值和下标组成
- map中的key和value用来存什么的
key存储数组的元素,value存储该元素的下标
代码:
class 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 ira = map.find(target - nums[i]);
if(ira != map.end()) return {ira->second,i};//ira->first是map的key值,ira->second是map的value值
map.insert(pair<int,int>(nums[i],i));
}
return {};
}
};