字母异位词分组
思路分析:
本题实际意义是将字母组成相同的单词分为一组,那么我们显然首先想如何将“字母组成相同”
这个条件转化,他们之间的区别实际上就是字母顺序,那么通过对单词排序其实就可以让他们没有差别。
而排序后相同的单词分为一组,那么区分组与组之间的就是单词了,所以我们可以用哈希表的方式,让排序后的单词为键,排序前的单词装在一个vector<string>里,因为我们要返回vector<vector<string>>的类型。
代码如下:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
unordered_map<string,vector<string>> mp;
for(const auto &str : strs)//这里加上const避免修改错了
{
string a=str;
sort(a.begin(),a.end());
mp[a].push_back(str);
}
vector<vector<string>> ans;
for(auto it =mp.begin();it!=mp.end();++it)//注意迭代器的范围,不是小于
{
ans.emplace_back(it->second);//一次性插入一个vector数组
}
return ans;
}
最长连续序列
思路分析:
本题要求时间复杂度在O(n),而数据范围:0 <= nums.length <= 1e5;-1e9 <= nums[i] <= 1e9;
实际对应着acm模式的1s内,因为计算机1s差不多运行1e8次。
题目要求我们O(n),那么就不能用sort排序了,而只能遍历一次,再不能排序的情况下,要想找到单个数的前后是否连续,或者说前后是否存在,我们可以想到unordered_map的find函数时间复杂度为O(1)。
代码如下:
int longestConsecutive(vector<int>& nums) {
unordered_map<int,int> m;
int result=0;//记录结果
for(const auto& it : nums)
{
if(m.find(it)!=m.end())continue;//已经存在就不再插入,相当于去重
int left =m.find(it-1)==m.end() ? 0 : m[it-1];//查找n-1其实是检查连续性并记录连续个数
int right = m.find(it+1)==m.end() ? 0 : m[it+1];
int len = left +right+1;//左边加上右边加上自己就是连续长度,原因在于下面的赋值
m[it]=1;
m[it-left]=m[it+right]=len;//把连续长度记录在两边
result = max(result,len);
}
return result;
}
除了unordered_map,这里还用了两个变量来记录左右连续长度,而unordered_map的值则记录了连续段的长度,只要你连上了某一连续段的边,就能加上全部长度,大大缩减遍历时间。