LeetCode 567. 字符串的排列
给你两个字符串 s1
和 s2
,写一个函数来判断 s2
是否包含 s1
的排列。如果是,返回 true
;否则,返回 false
。
换句话说,s1
的排列之一是 s2
的 子串 。
示例 1:
输入:s1 = "ab" s2 = "eidbaooo"
输出:true
解释:s2 包含 s1 的排列之一 ("ba").
method
维护一个s1.size()
大小的滑动窗口,比较窗口内字符的出现次数是否和s1
的字符出现次数相等
bool checkInclusion(string s1, string s2) {
int m = s1.size(), n = s2.size();
if (m > n) return false;
vector<int> count1(26);
vector<int> count2(26);
for (int i = 0; i < m; i++) {
count1[s1[i] - 'a']++;
count2[s2[i] - 'a']++;
}
if (count1 == count2) return true;
for (int i = m; i < n; i++) {
count2[s2[i - m] - 'a']--;
count2[s2[i] - 'a']++;
if (count1 == count2) return true;
}
return false;
}
因为每次只是增加一个字符,减少一个字符,但都要count1
和count2
整个数组的比较
可以用一个变量distance
记录有多少个字符存在差异,然后用一个数组cnt
来记录窗口内的字符出现次数与s1
的字符出现次数的差值,只要差值不为0,变量distance
就为1
- 每次增加一个字符
x
时,如果原本cnt[x]=0
,那么增加字符x
后cnt[x]
就不为0,所以distance
加1,如果加上x
后,cnt[x]=0
,那distance
减1 - 每次减少一个字符
y
时,如果原本cnt[y]=0
,那么减少字符y
后cnt[y]
就不为0,所以distance
加1,如果减去y
后,cnt[y]=0
,那distance
减1 - 如果
distance=0
,说明没有差异,窗口内的子串和s1
的字符时一样的
bool checkInclusion(string s1, string s2) {
int m = s1.size(), n = s2.size();
if (m > n) return false;
vector<int> cnt(26);
for (int i = 0; i < m; i++) {
cnt[s1[i] - 'a']--; // s1减
cnt[s2[i] - 'a']++; // s2加
}
int distance = 0;
for (auto n : cnt) {
if (n != 0) distance++;
}
if (distance == 0) return true;
for (int i = m; i < n; i++) {
int x = s2[i] - 'a'; // 要加上的
int y = s2[i - m] - 'a'; // 要减去的
if (cnt[x] == 0) distance++;
cnt[x]++;
if (cnt[x] == 0) distance--;
if (cnt[y] == 0) distance++;
cnt[y]--;
if (cnt[y] == 0) distance--;
if (distance == 0) return true;
}
return false;
}