一、题目展示
二、代码解法
三、代码整体思路
四、代码详细解释
一、题目展示

二、代码解法
cpp
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
int slen=s.size(),plen=p.size();
if(slen<plen)
{
return vector<int>();
}
vector<int> ans;
vector<int> scont(26);
vector<int> pcont(26);
for(int i=0;i<plen;i++)
{
++scont[s[i]-'a'];
++pcont[p[i]-'a'];
}
if(scont==pcont)
{
ans.emplace_back(0);
}
for(int i=0;i<slen-plen;i++)
{
--scont[s[i]-'a'];
++scont[s[i+plen]-'a'];
if(scont==pcont)
{
ans.emplace_back(i+1);
}
}
return ans;
}
};
三、代码整体思路
这段 代码定义了一个名为 findAnagrams
的函数,它的主要功能是在字符串 s
中找出所有字符串 p
的异位词的起始索引。异位词指的是由相同字母重排列形成的字符串(包括相同的字符串)。
这段代码使用滑动窗口和字符频率统计的方法来解决问题。通过比较滑动窗口内字符的频率和目标字符串 p
中字符的频率,找出所有异位词的起始位置。下面我们逐行来详细解释这段代码。
四、代码详细解释
类和函数定义:
cpp
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
- 定义了一个名为
Solution
的类,其中包含一个公共成员函数findAnagrams
。 findAnagrams
函数接受两个字符串s
和p
作为参数,并返回一个整数向量,该向量包含字符串s
中所有p
的异位词的起始索引。
处理边界情况:
cpp
int sLen = s.size(), pLen = p.size();
if (sLen < pLen) {
return vector<int>();
}
- 首先获取字符串
s
和p
的长度,分别存储在变量sLen
和pLen
中。 - 如果字符串
s
的长度小于p
的长度,说明s
中不可能存在p
的异位词,直接返回一个空的整数向量。
初始化变量:
cpp
vector<int> ans;
vector<int> sCount(26);
vector<int> pCount(26);
ans
:用于存储所有找到的异位词的起始索引。sCount
:一个长度为 26 的整数向量,用于统计滑动窗口内每个小写字母的出现频率。pCount
:一个长度为 26 的整数向量,用于统计字符串p
中每个小写字母的出现频率。
scont
和 pcont
:它们都是长度为 26 的 vector<int>
类型的向量,用于分别记录字符串 s
和 p
中每个小写字母的出现次数。因为小写字母 a
到 z
可以通过减去字符 'a'
的 ASCII 值映射到 0 到 25 的索引范围,所以使用长度为 26 的向量来存储每个字母的计数
初始化滑动窗口和目标字符串的字符频率:
- 遍历字符串
p
的长度,同时更新sCount
和pCount
向量。 s[i] - 'a'
和p[i] - 'a'
是将字符映射到 0 - 25 的索引,对应小写字母a
到z
。例如,字符'a'
映射到索引 0,'b'
映射到索引 1,以此类推。- 通过
++sCount[s[i] - 'a']
和++pCount[p[i] - 'a']
分别统计滑动窗口内和字符串p
中每个字符的出现频率。
检查初始窗口是否为异位词:
cpp
if (sCount == pCount) {
ans.emplace_back(0);
}
这里的emplace_back 函数 是 std::vector 容器提供的成员函数 。它的作用是在 vector 的尾部直接构造新元素,而不是像 push_back 那样先创建一个临时对象,再将其拷贝或移动到 vector 尾部。这意味着在某些情况下(比如构造复杂对象时),emplace_back 能避免不必要的对象拷贝或移动操作,从而提高效率。
这个判断是比较 sCount
和 pCount
向量是否相等。如果相等,说明字符串 s
的前 pLen
个字符组成的子串是 p
的异位词,将起始索引 0 添加到 ans
向量中。
滑动窗口移动:
cpp
for (int i = 0; i < sLen - pLen; ++i) {
--sCount[s[i] - 'a'];
++sCount[s[i + pLen] - 'a'];
if (sCount == pCount) {
ans.emplace_back(i + 1);
}
}
- 使用一个循环来移动滑动窗口,窗口的大小始终保持为
pLen
。 --sCount[s[i] - 'a']
:将滑动窗口最左边的字符的频率减 1,表示该字符离开窗口。++sCount[s[i + pLen] - 'a']
:将滑动窗口最右边的下一个字符的频率加 1,表示该字符进入窗口。- 每次移动窗口后,比较
sCount
和pCount
向量是否相等。如果相等,说明当前滑动窗口内的子串是p
的异位词,将当前窗口的起始索引i + 1
添加到ans
向量中。
返回结果:
cpp
return ans;
- 最后返回存储所有异位词起始索引的
ans
向量。