
🔥小叶-duck:个人主页
❄️个人专栏 :《Data-Structure-Learning》《C++入门到进阶&自我学习过程记录》
《算法题讲解指南》--优选算法
《算法题讲解指南》--递归、搜索与回溯算法
《算法题讲解指南》--动态规划算法
✨未择之路,不须回头
已择之路,纵是荆棘遍野,亦作花海遨游
目录
58.存在重复元素I
题目链接:
题目描述:

题目示例:

解法(哈希表):
算法思路:
分析一下题目,出现「至少两次」的意思就是数组中存在着重复的元素,因此我们可以无需统计元素出现的数目。仅需在遍历数组的过程中,检查当前元素「是否在之前已经出现过」即可。
因此我们可以利用哈希表,仅需存储数「组内的元素」。在遍历数组的时候,一边检查哈希表中是否已经出现过当前元素,一边将元素加入到哈希表中。
C++算法代码:
cpp
class Solution {
public:
bool containsDuplicate(vector<int>& nums)
{
if(nums.size() == 1)
{
return false;
}
unordered_map<int, int> hash;
for(int i = 0; i < nums.size(); i++)
{
hash[nums[i]]++;
if(hash[nums[i]] > 1)
{
return true;
}
}
return false;
}
};
59.存在重复元素II
题目链接:
题目描述:

题目示例:

解法(哈希表):
算法思路:
解决该问题需要我们快速定位到两个信息:
两个相同的元素;
这两个相同元素的下标。
因此,我们可以使用「哈希表」,令数组内的元素做key值,该元素所对应的下标做val值,将「数组元素」和「下标」绑定在一起,存入到「哈希表」中。
思考题:
如果数组内存在大量的「重复元素」,而我们判断下标所对应的元素是否符合条件的时候,需要将不同下标的元素作比较,怎么处理这个情况呢?
答:这里运用了一个「小贪心」。
我们按照下标「从小到大」的顺序遍历数组,当遇到两个元素相同,并且比较它们的下标时,这两个下标一定是距离最近的,因为:
如果当前判断符合条件直接返回true,无需继续往后查找。
如果不符合条件,那么前一个下标一定不可能与后续相同元素的下标匹配(因为下标在逐渐变大),那么我们可以大胆舍去前一个存储的下标,转而将其换成新的下标,继续匹配。
C++算法代码:
cpp
class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k)
{
//解法:哈希表
if(k == 0)
{
return false;
}
unordered_map<int, int> hash;
for(int i = 0; i < nums.size(); i++)
{
if(hash.count(nums[i]))
{
if(i - hash[nums[i]] <= k)
{
return true;
}
}
hash[nums[i]] = i;
}
return false;
}
};
60.字母异位词分组
题目链接:
题目描述:

题目示例:

解法(哈希表+排序):
算法思路:
互为字母异位词的单词有一个特点:将它们「排序」之后,两个单词应该是「完全相同」的。
所以,我们可以利用这个特性,将单词按照字典序排序,如果排序后的单词相同的话,就划分到同一组中。
这时我们就要处理两个问题:
排序后的单词与原单词需要能互相映射;
将排序后相同的单词,「划分到同一组」;
利用语言提供的「容器」的强大的功能就能实现这两点:
将排序后的字符串( string )当做哈希表的 key 值;
将字母异位词数组( vector<string> )当成 val 值。
定义一个「哈希表」即可解决问题。
C++算法代码:
cpp
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs)
{
unordered_map<string, vector<string>> hash;
//键为string,表示的是strs每个字符串通过ascll码值重排序的结果
//如果存在则说明两者是异位词,如果不存在则相当于插入
//值为vector<string>,表示的是对应相同的键在vector<string>存放的所有结果
//后续只需要取出来即可
//1、把所有的字母异位词分组
for(auto str : strs)
{
string tmp = str;
sort(tmp.begin(), tmp.end());
hash[tmp].push_back(str);
}
//2、结果从哈希表提取出来
vector<vector<string>> ret;
for(auto [k, v] : hash)
{
//k对应的是键,v对应的是值,我们是需要将hash中的值也就是vector<string>放入ret中
ret.push_back(v);
}
return ret;
}
};
算法总结及流程解析:

结束语
到此,58.存在重复元素I,59.存在重复元素II,60.字母异位词分组 这三道算法题就讲解完了。**存在重复元素I,使用哈希表快速检测数组中是否存在重复元素,只需判断元素是否已存在哈希表中即可。存在重复元素II,在哈希表中同时存储元素和下标,检查相同元素的下标差是否≤k,利用贪心思想优化查找过程。字母异位词分组,将排序后的字符串作为哈希表键值,相同键值的字符串归为一组,实现字母异位词的高效分组。**希望大家能有所收获!