哈希表
数值很小,用数组;数值很大,用set(集合);如果有对应关系,就用map(映射)
数组:将自身的序号(索引)与实际数据大小画等号
242.有效的字母异位词
判读两个序列中的字母是否相同(个数相同即可,顺序可以不同)
思路
暴力解法,双排序寻找字母
看完代码随想录之后的思路:
利用哈希表,加入数组。重要的是利用了索引,使得原来无序的东西有了索引,查找起来更快。
原始无序的东西需要遍历,而有序的东西只要根据索引直接查找即可。
class Solution {
public:
bool isAnagram(string s, string t) {
int record[26]={0};
for(int i=0;i<s.size();i++)
{
record[s[i]-'a']++;
}
for(int i=0;i<t.size();i++)
{
record[t[i]-'a']--;
}
for(int i=0;i<26;i++)
{
if(record[i]!=0)
{
return false;
}
}
return true;
}
};
收获:
astii值直接相减就可以,得到的就是数值差。
数组的定义,要想让所有数值为0 ,不能=0,而是写={0}
349. 两个数组的交集
寻找两个数组中相同的元素,并且将重复的元素删除
思路
数组哈希值求解,但又隐约感觉需要用到映射(单个元素会出现多次)
看完代码随想录之后的思路:
用哈希的集合(set)求解,重复元素删除直接用unordered_set,查找直接用find函数
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> result_set;
unordered_set<int> nums_set(nums1.begin(),nums1.end());
for(int num:nums2)
{
if(nums_set.find(num)!=nums_set.end())
{
result_set.insert(num);
}
}
return vector<int>(result_set.begin(),result_set.end());
}
};
哈希数组法,用一个哈希数组来对其中一个数组元素的出现计数,然后使用另一个数组元素作为索引来核实重复。
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> result_set;
int hash[1005]={0};//这里是题目说了小于1000
for(int num:nums1)
{
hash[num]=1;
}
for(int num:nums2)
{
if(hash[num]==1)
{
result_set.insert(num);
}
}
return vector<int>(result_set.begin(),result_set.end());
}
};
遇到的困难:
- 如何删除重复的元素:unordered_set的数据类型,在代码随想录链表综述里
- 拷贝已有容器,删除重复元素后生成新容器:
set 类模板还支持取已有 set 容器中的部分元素,来初始化新 set 容器
由此初始化的 copyset 容器,其内部仅存有如下 2 个 string 字符串:std::set<std::string> myset{ "http://c.biancheng.net/java/", "http://c.biancheng.net/stl/", "http://c.biancheng.net/python/" }; std::set<std::string> copyset(++myset.begin(), myset.end());"http://c.biancheng.net/python/" "http://c.biancheng.net/stl/"
for循环的冒号写法
在C++11中,我们可以在for循环填加冒号 : 来简化这一过程:
//随机定义的数组 int array[10] = { 54, 23, 78, 9, 15, 18, 63, 33, 87, 66 }; for (auto a : array) { cout << a << " "; //输出:54 23 78 9 15 18 63 33 87 66 }如果传入的迭代参数类型为非引用时,做的是值拷贝,因此修改数据是无效的。如果传递的是引用,则可以改变原数组的值。
find的判断:
如下为 find() 函数的语法格式:
InputIterator find (InputIterator first, InputIterator last, const T& val);其中,first 和 last 为输入迭代器,[first, last) 用于指定该函数的查找范围;val 为要查找的目标元素。
该函数会返回一个输入迭代器,当 find() 函数查找成功时,其指向的是在 [first, last) 区域内查找到的第一个目标元素;如果查找失败,则该迭代器的指向和 last 相同。
所以,!=说明在中间找到了,==说明没找到,返回了最后last的迭代器
收获:
数组哈希:有两列数据,不是给两列数据各自开一个数组,然后比较。而是使用一个数组,两列数据充当索引。
定义数组时,一定写int hash={0}!!!不定义0会报错!!
重点:
数组的哈希映射是最快的
第202题. 快乐数
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为 1,那么这个数就是快乐数。
如果 n 是快乐数就返回 True ;不是,则返回 False 。
思路
想使用数组哈希表
看完代码随想录之后的思路:
因为出现的和不确定大小,所以使用集合哈希更合适。
先判断拆分后的平方和是否达到1,然后判断之前是否出现过。
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> set;
while(1)
{
int sum=getSum(n);
if(sum==1)return true;
if(set.find(sum)!=set.end())
{
return false;
}
else
{
set.insert(sum);
}
n=sum;
}
}
};
遇到的困难:
1. 拆分求平方和:余数求平方,然后除以10,接着循环,直到所有位算过一遍,除以10后成为0,结束循环
2. 出现的错误:
1. 平方和记得是+=,少写一个+,整个意思就不同了
2. 判断是否在集合中:不等于end,说明出现过了,进入循环,返回false,否则插入。不能搞反了
收获:
find、end、insert都是方法,用set点出来
1. 两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个整数,并返回他们的数组下标。
思路:
暴力解法,双循环找前面的元素中是否和当前元素相加等于target
看完代码随想录之后的思路:
哈希map,看讲解中说道map找起来要比循环找起来快
循环一遍数组,遍历每个元素时,找前面是否出现过匹配的元素,出现了就返回,没出现就插入map
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 iter=map.find(target-nums[i]);
if(iter!=map.end())
{
return {iter->second,i};
}
else
{
map.insert(pair<int,int>(nums[i],i));
}
}
return {};
}
};
遇到的困难:
map的定义: std::unordered_map <int,int> map;
map下find的定义:auto iter = map.find(target - nums[i]);
两个数的返回值,用 { } 框起来
map元素的value值表示:iter->second
map中key和value插入:map.insert(pair<int, int>(nums[i], i));
收获:
map的时间复杂度比遍历低(为什么?)
重点:
为什么要用哈希法:判断是否在历史中出现过
为什么用map:因为出现了需要同时存储两种信息的情况。set中是无序的元素集合,没有索引;而数组是因为没有确定的范围。
用unordered_map:无序不重复更适合这种情况
为什么key存值value存下标:查找的是值,所以用key存值
map是用来存遍历过的元素,所以最后的insert不能省
452



被折叠的 条评论
为什么被折叠?



