Problem: 438. 找到字符串中所有字母异位词
题目描述
思路
本题目在使用滑动窗口技巧的基础上先要对原字符串做一些处理,具体的:
1.利用数组设置一个位图将字符串P存入数组(下标索引为小写英文字母的顺序,对应存储的值为其个数:vector needs(26,0);needs[p[i] - ‘a’]++;);
2.利用同样的方式将字符串S中的小于等于字符串P中的子串先存入另一个位图mached;
3.从字符串S中大于字符串P的部分开始,每次利用双指针循环先添加一个字符进mached,再在原来的基础上减去一个末尾一个字符以达到动态维护滑动窗口的操作,在动态维护滑动窗口的过程中需要同时比较两个位图needs和matched是否一致,若一致则说明当前位置为一个字母异位词的起始位置,并将其记录到一个结果集中
解题方法
1.编写比较两个数组给定范围所存储内容是否一致的函数same(vector& need, vector& matched);
2.获取字符串S和P的长度,sLen、pLen;
3.创建位图needs,将字符串P中的字符和其对应的个数存入(vector needs(26,0);needs[p[i] - ‘a’]++;);
4.定义两个指针int starP = 0;int endP = 0;,并且利用指针endP将字符串S中长度等于字符串P长度的子串存入另一个位图matched(vector matched(26,0);while (endP < pLen) {matched[s[endP] - ‘a’]++;endP++;});
5.定义结果集vector result;,并判断一次此时位图needs和matched是否完全一致,若一致则表明初始时S中的一个子串就为一个字母异位词;
6.在上述操作中已经是抽象地完成了滑动窗口的创建,再按照思路中的3进行滑动窗口的动态维护;
复杂度
时间复杂度:
O ( n ) O(n) O(n),其中 n n n为字符串S的长度(假设 s L e n > > p L e n sLen>>pLen sLen>>pLen);
空间复杂度:
O ( 1 ) O(1) O(1)
Code
class Solution {
public:
/**
* Sliding window
*
* @param s The string given to be matched
* @param p Substring
* @return vector<int>
*/
vector<int> findAnagrams(string s, string p) {
int sLen = s.length();
int pLen = p.length();
if (pLen > sLen) {
return {};
}
vector<int> needs(26,0);
for (int i = 0; i < pLen; ++i) {
needs[p[i] - 'a']++;
}
vector<int> matched(26,0);
int starP = 0;
int endP = 0;
vector<int> result;
while (endP < pLen) {
matched[s[endP] - 'a']++;
endP++;
}
if (same(needs, matched)) {
result.push_back(starP);
}
while (starP < sLen && endP < sLen) {
matched[s[starP] - 'a']--;
matched[s[endP] - 'a']++;
starP++;
endP++;
if (same(needs, matched)) {
result.push_back(starP);
}
}
return result;
}
private:
/**
*Determines whether the values in two arrays (within a given range) are equal
*
* @param need Judgment reference array
* @param matched Array to match each time
* @return bool
*/
bool same(vector<int>& need, vector<int>& matched) {
for (int i = 0; i < need.size(); ++i) {
if (need[i] != matched[i]) {
return false;
}
}
return true;
}
};