Day6
主要注意的是:我们hash表主要是用来存值的,只不过map比set更加丰富点功能,里面不仅会存放数值,而且可以存放相应的键值对。
unordered_map
和 unordered_set
是 C++ 标准模板库(STL)中的两种容器,它们都基于哈希表实现,但主要区别在于它们存储和处理数据的方式:
unordered_map
- 键值对存储:
unordered_map
存储的是键值对(key-value pairs)。每个元素是一个键和一个值的组合。 - 唯一键:在
unordered_map
中,每个键都是唯一的。不能有两个元素具有相同的键。 - 直接访问:可以直接通过键来访问对应的值。
- 用途:当你需要存储和检索键值对时(例如,字典),
unordered_map
是一个好选择。
示例:
std::unordered_map<std::string, int> map;
map["apple"] = 1;
map["banana"] = 2;
// 访问键 "apple" 的值
int value = map["apple"];
unordered_set
- 单值存储:
unordered_set
只存储值,没有键值对的概念。每个元素只包含一个单独的数据项。 - 唯一性:集合中的每个元素都是唯一的,不允许重复。
- 用途:当你只需要存储一组唯一元素,并且不需要映射到其他值时,
unordered_set
是合适的选择。
示例:
std::unordered_set<int> set;
set.insert(1);
set.insert(2);
// 检查值 1 是否存在
bool is_present = set.find(1) != set.end();
总结
- 使用
unordered_map
当你需要存储键值对,并且需要通过键来高效检索值。 - 使用
unordered_set
当你只需要存储一组唯一元素,不需要与之关联的值。
这两个容器都提供了高效的插入、删除和查找操作(平均时间复杂度为 O(1)),但这取决于哈希函数的质量和冲突解决机制。由于它们是基于哈希表实现的,因此它们不保持元素的有序性。
第454题.四数相加II
给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0。
为了使问题简单化,所有的 A, B, C, D 具有相同的长度 N,且 0 ≤ N ≤ 500 。所有整数的范围在 -2^28 到 2^28 - 1 之间,最终结果不会超过 2^31 - 1 。
例如:
输入:
- A = [ 1, 2]
- B = [-2,-1]
- C = [-1, 2]
- D = [ 0, 2]
输出:
2
解释:
两个元组如下:
- (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
- (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0
这个题目主要是找到四个整数数组中的四个数值之和为0的对应下标的个数,这个题目就可以借鉴之前有效的字母异位词,先将前两个数组之和放入哈希表中,然后遍历剩余的两个数组,统计哈希表中对应值出现的次数进行相加。
class Solution
{
int foursumCount(vector<int>& nums1,vector<int>& nums2,vector<int>& nums3,vector<int> nums4)
{
unordered_map<int,int> umap;//建立一个哈希表存放前两个数组之和及其键值对,这里应该将其表示为出现的次数。
for(int a:nums1)
{
for(int b:nums2)
{
umap[a+b]++;
}
}
int count =0;
for(int c:nums3)
{
for(int d:nums4)
{
if(umap.find(0-(c+d))!=umap.end())//哈希表中寻找到了想要的值
{
count+=umap[0-(c+d)];//将对应值的次数进行相加。
}
}
return count;
}
}
};
本题目的一个主要的困难点就在于我以前没有进一步地去了解过哈希表,可能是数据结构学习的不够到位。
383. 赎金信
给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串 ransom 能不能由第二个字符串 magazines 里面的字符构成。如果可以构成,返回 true ;否则返回 false。
(题目说明:为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思。杂志字符串中的每个字符只能在赎金信字符串中使用一次。)
注意:
你可以假设两个字符串均只含有小写字母。
canConstruct(“a”, “b”) -> false
canConstruct(“aa”, “ab”) -> false
canConstruct(“aa”, “aab”) -> true
思路:其实遇到类似字符串这种数值不是很大的都是使用数组模拟哈希表进行操作。
class Solution
{
bool canConstruct(string ransom,string magazine)
{
int record[26]={0};
if(ransom.size()>magazine.size())
{
return false;
}
for(int i=0;i<magazine.size();i++)
{
record[magazine[i]-'a']++;
}
for(int j=0;j<ransom.size();j++)
{
record[ransom[j]-'a']--;
if(record[ransom[j]-'a']<0)
{
return false;
}
}
return true;
}
};
15. 三数之和
给你一个整数数组 nums
,判断是否存在三元组 [nums[i], nums[j], nums[k]]
满足 i != j
、i != k
且 j != k
,同时还满足 nums[i] + nums[j] + nums[k] == 0
。请
你返回所有和为 0
且不重复的三元组。
**注意:**答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。
示例 2:
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。
示例 3:
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。
提示:
-
3 <= nums.length <= 3000
-
-105 <= nums[i] <= 105
-
`class Solution {
public:
vector<vector> threeSum(vector& nums) {
vector<vector> result;
sort(nums.begin(),nums.end());
for(int i=0;i<nums.size();i++)
{
if(nums[i]>0)
return result;if(i>0&&nums[i]==nums[i-1]) { continue; } int left=i+1; int right = nums.size() - 1; while(right>left) { if(nums[i]+nums[left]+nums[right]>0) { right--; } else if(nums[i]+nums[left]+nums[right]<0) { left++; } else { result.push_back(vector<int>{nums[i], nums[left], nums[right]}); // 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 while (right > left && nums[right] == nums[right - 1]) right--; while (right > left && nums[left] == nums[left + 1]) left++; // 找到答案时,双指针同时收缩 right--; left++; } } } return result;
}
};`