代码随想录第6天 | ●哈希表理论基础●242.有效的字母异位词●349. 两个数组的交集●202. 快乐数●1. 两数之和
题目:242.有效的字母异位词
思路:
1.ASCII和哈希函数,存入数组,比较数组相等否
2.首先选择数据结构,题目只有小写字母,ASCII连续,选用数组,一个字符串遍历,在哈希数组中存入字母出现频率,第二个字符串遍历,做减法。(不需要记ASCII,直接减字母,编译器自己算)
时间复杂度: O(n)
空间复杂度: O(1)
坑:
无
补充:
哈希表理论基础
- 哈希表是hash table 又叫散列表, 多用于快速判断某意思元素是否在集合里。(数组是一个哈希表。)
- 哈希函数hash function把 实际的目标 映射到 哈希表上。
- 哈希碰撞(冲突) 实际目标映射到了相同索引下标的位置。解决方法:
①拉链法:冲突的元素 存储在链表中
②线性探测法:要保证tableSize 大于dataSize,冲突的元素 存储在冲突位置往后的空位上。
常见的哈希结构 - 数组
- set(集合)
- map(映射)
set和map的底层实现及优劣表
集合set | 底层实现 | 是否有序 | 数值是否可以重复 | 能否更改数值 | 查询效率 | 增删效率 |
---|---|---|---|---|---|---|
std::set | 红黑树 | 有序 | 否 | 否 | O(log n) | O(log n) |
std::multiset | 红黑树 | 有序 | 是 | 否 | O(logn) | O(logn) |
std::unordered_set | 哈希表 | 无序 | 否 | 否 | O(1) | O(1) |
使用集合来解决哈希问题的时候,优先使用unordered_set,因为它的查询和增删效率是最优的,
如果需要集合是有序的,那么就用set,
如果要求不仅有序还要有重复数据的话,那么就用multiset。
映射map | 底层实现 | 是否有序 | 数值是否可以重复 | 能否更改数值 | 查询效率 | 增删效率 |
---|---|---|---|---|---|---|
std::map | 红黑树 | key有序 | key不可重复 | key不可修改 | O(logn) | O(logn) |
std::multimap | 红黑树 | key有序 | key可重复 | key不可修改 | O(log n) | O(log n) |
std::unordered_map | 哈希表 | key无序 | key不可重复 | key不可修改 | O(1) | O(1) |
红黑树
红黑树是一种平衡二叉搜索树,所以key值是有序的,但key不可以修改,改动key值会导致整棵树的错乱,所以只能删除和增加。
题目:349.两个数组的交集
思路:
- 类似上题,使用数组,根据元素的数值,存入数组对应下标中 但如果数值很大,映射到数组下标就不合适。
- 该题去重,则选择unordered_set
时间复杂度: O(n + m) m 是最后要把 set转成vector
空间复杂度: O(n)
坑:
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
if(nums1.size()<nums2.size()){
nums1.swap(nums2);
}
unordered_set<int> hash_set(nums1.begin(),nums1.end());
unordered_set<int> result_set;
for(int num: nums2){
if(hash_set.find(num)!=hash_set.end()){
result_set.insert(num);
//在集合hash_set中使用find函数查找num,找到返回一个指向该元素的正向迭代器,反之,返回一个类似end()的迭代器
//找到则将该元素存入结果集合result_set中
}
}
return vector<int>(result_set.begin(),result_set.end());
//因为函数返回类型是vector 所以转换一下类型
}
};
补充:
set集合
C++ STL unordered_set容器
成员方法 | 功能 |
---|---|
find(key) | 查找以值为 key 的元素,如果找到,则返回一个指向该元素的正向迭代器;反之,则返回一个指向容器中最后一个元素之后位置的迭代器(一个与end() 方法相同的迭代器)。 |
count(key) | 在容器中查找值为 key 的元素的个数。 |
empty() | 若容器为空,则返回 true;否则 false。 |
size() | 返回当前容器中存有元素的个数。 |
范围for循环
范围循环:
for (类型 element : myVector) {
std::cout << element << " ";
}
题目:202.快乐数
思路:
对n取余存入unordered_set 然后判断和是否为1,题目说可能无限循环,不知怎么判断
- 无限循环是sum会重复出现 ,所以将每次循环的sum存入sums_set, 查找是否存在。
2.看leetcode题解:双指针
坑:
1.数位分离,求平方和,可以简单的while和sum,不用多一步将个个数位上的值存入nums_set
2. % 是整数取余,/ 是除号
class Solution {
public:
bool isHappy(int n) {
unordered_set<int> sums_set;
int sum = 0;
while (sum != 1) {
sum=0; //错误,sum 没有更新为0;
while (n ) {// 错误 while的循环判断条件 不是n/10,这样会少判断元素
sum+=(n%10)*(n%10);
n = n / 10;
}
if(sums_set.find(sum)!=sums_set.end()){
return false;
}else{
sums_set.insert(sum);
}
n=sum;
}
return true;
}
};
题目:1.两数之和
思路:
- 暴力法,枚举数组中的每一个数 x,寻找数组中是否存在 target - x。遍历,与目标值作差,在数组中寻找差值
- 升级,方法一时间复杂度较高在于,target-1的遍历, 所以将遍历过的值x和下标保存到一个集合,之后遍历的时候来询问这个集合 ,target-x是否遍历过。因为需要保存值和下标 所以选用map,因为无序,-->unordered_map
时间复杂度: O(n)
空间复杂度: O(n)
坑:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> nums_map;
vector<int> result;
for(int i=0;i<nums.size();i++){
if(nums_map.find(target-nums[i])!=nums_map.end()){
result.push_back(i);
result.push_back(nums_map.at(target-nums[i]));
return result;
//优化 使用迭代器
}else{
nums_map.insert({nums[i],i});
//map以键值对的pair的方式插入{}
}
}
return result;
}
};
/*
使用迭代器
// 遍历当前元素,并在map中寻找是否有匹配的key
auto iter = map.find(target - nums[i]);
if(iter != map.end()) {
return {iter->second, i};
}
// 如果没找到匹配对,就把访问过的元素和下标加入到map中
map.insert(pair<int, int>(nums[i], i));
//没有返回return {};
*/
补充:
map相关
C++之STL整理(3)之map 用法(创建、赋值、方法)整理
STL 中的map是一个关联容器,它存储的元素都是键值对(key-value pair),并且根据键(key)自动排序的容器。map不允许键重复,每个键在map中只能出现一次。
map容器的每一个元素都是一个pair结构(pair<t1,t2>)的数据。
map容器的迭代器first和second,分别对应key 和value。 通过map->first;获得对应的值
pair结构
pair 通常用于将两个值组合成一个单一的实体,以便可以作为一个整体进行传递或返回。
这两个元素分别被称为 first 和 second。
包含头文件:#include
迭代器
迭代器是一种检查容器内元素并遍历元素的数据类型,通常用于对C++中各种容器内元素的访问,但不同的容器有不同的迭代器,
C++ 迭代器(iterator)超详解
迭代器的通用功能
- 比较两个迭代器是否相等(==、!=)。
- 前置和后置递增运算(++)。
- 读取元素的解引用运算符(*)。只能读元素,也就是解引用只能出现在赋值运算符的右边。
- 箭头运算符(->),解引用迭代器,并提取对象的成员。
今日总结
需要复习map,和迭代器的用法
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步