热题100 - 49. 字母异位词分组
- 链接:49. 字母异位词分组 - 力扣(LeetCode)
- 思路:
- 字母异位词的特征:字母相同,但排列不同的字符串 ==> 故对其排序后都一定是相同的(因为每种字母的个数都是相同的)
- 对每个单词按各自的字母顺序排序,新形成的单词作为hash表的key,原单词作为value,最终可构建hash表如下:
- ![[Pasted image 20231109110616.png]]
- 如何返回hash.second答案?
- 将hash.second按照key来分组,push进vector数组中
- vector数组的每个元素,也是vector数组。
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
//map<排序后单词,同排序的原单词数组>
unordered_map<string,vector<string>> strVec;
//1.给每个单词,按重排序后进行分组
for(auto const &str:strs) //②
{
//1.1 ktmp:重排序后的新单词,作为key
string ktmp = str;
sort(ktmp.begin(),ktmp.end());
//1.2 把原单词分到自己的小组
strVec[ktmp].emplace_back(str); //①
}
//2.把分组结果取出,合并到res中
vector<vector<string>> res;
for(auto const &v:strVec)
{
res.emplace_back(v.second);
}
return res;
}
};
- 优化:
- ①
emplace_back()
和push_back()
的区别- 提交后查看相同思路但相对速度快一点的写法,看到采用
emplace_back()
替代push_back()
,于是二者进行对比了解 - 二者区别在于底层实现的机制不同。
push_back()
向容器尾部添加元素时,首先会创建这个元素,然后再将这个元素拷贝或者移动到容器中(如果是拷贝的话,事后会自行销毁先前创建的这个元素)- 而
emplace_back()
在实现时,则是直接在容器尾部创建这个元素,省去了拷贝或移动元素的过程。
- 提交后查看相同思路但相对速度快一点的写法,看到采用
- ② 或在auto时采用
for (auto const &s : strs)
也会快一些 - ①和②的优化都是在于减少拷贝,所以会快一点
- ①
热题100 - 1. 两数之和
-
思路:
- 将每个数字作为key,对应下标作为value存到hash表中;再二次遍历数组每个数字num,逐一找
hash[target-num]
==> 因为题目表示一定有答案,且唯一 ==> 存在如下问题:- ① 两个相同的数字,第一个数字的下标会被第二个数字下标所覆盖
- ② 遍历两次效率有问题
- 故思考:由于题目表示一定有答案 ==> 于是采用边遍历,边找
- 若找到了,就直接返回
- 若没找到,就先存到hash表里,因为可能当前的数会被后面的数匹配上
- 将每个数字作为key,对应下标作为value存到hash表中;再二次遍历数组每个数字num,逐一找
-
细节:
- ①hash中找是否存在这个key值,不能根据key对应的value是否为0来找:因为在hash表里找不存在的key时,它的value也是0;容易和下标刚好为0的数混在一起 ==> 得用find
- find()函数:会查找容器中是否存在特定值,如果不存在会指向末尾 end;
- ②
- find返回的是指针,读取需要
it->second
;若根据key读value,则iVal[target-nums[i]]
即可 - 因为哈希表里存的是在i之前的数,所以找到了应先返回哈希表里找到数的下标
- find返回的是指针,读取需要
- ③ 虽然题目表示有且仅有唯一解,但仍需
return{}
- ④ 从头枚举,没能匹配就存入表中
- ①hash中找是否存在这个key值,不能根据key对应的value是否为0来找:因为在hash表里找不存在的key时,它的value也是0;容易和下标刚好为0的数混在一起 ==> 得用find
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
//创建哈希表
unordered_map<int,int> iVal;
//从数组头的下标开始遍历,i标记的是目标值在nums里的下标
for(int i=0;i<nums.size();i++)
{
auto it=iVal.find(target-nums[i]); //①
if(it!=iVal.end())
{
return {iVal[target-nums[i]],i};
//②或return {it->second,i};
}else{
iVal[nums[i]] = i;//④ 从头枚举,没能匹配就存入表中
}
}
return {};//③
}
};