题目描述
给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false 。
换句话说,s1 的排列之一是 s2 的 子串 。
示例1:
输入: s1 = “ab” s2 = “eidbaooo”
输出: true
解释: s2 包含 s1 的排列之一 (“ba”).
示例2:
输入: s1= “ab” s2 = “eidboaoo”
输出: false
提示
- 1 <= s1.length, s2.length <= 104
- s1 和 s2 仅包含小写字母
方法一:滑动窗口
解题思路
使用两个数组 cnt1 和 cnt2,cnt1 统计 s1 中各个字符的个数,cnt2 统计当前遍历的子串中各个字符的个数。
由于需要遍历的子串长度均为 n,我们可以使用一个固定长度为n的滑动窗口来维护 cnt2:滑动窗口每向右滑动一次,就多统计一次进入窗口的字符,少统计一次离开窗口的字符。然后,判断 cnt1 是否与 cnt2 相等,若相等则意味着 s1 的排列之一是 s2 的子串。
代码
class Solution {
public:
bool checkInclusion(string s1, string s2) {
int len1 = s1.size(), len2 = s2.size();
if(len1 > len2) return false;
vector<int> cnt1(26), cnt2(26);
for(int i = 0; i < len1; i++)
{
cnt1[s1[i] - 97]++;
cnt2[s2[i] - 97]++;
}
if(cnt1 == cnt2) return true;
for(int i = len1; i < len2; i++)
{
cnt2[s2[i] - 97]++;
cnt2[s2[i - len1] - 97]--;
if(cnt1 == cnt2) return true;
}
return false;
}
};
复杂度分析
- 时间复杂度:O( n + m + ∣ Σ ∣ n+m+|\Sigma| n+m+∣Σ∣)。
- 空间复杂度:O( ∣ Σ ∣ |\Sigma| ∣Σ∣)。
方法二:双指针
解题思路
初始时,仅统计 s1 中的字符,则 cnt 的值均不为正,且元素值之和为 -n。
然后用两个指针
left
\textit{left}
left 和
right
\textit{right}
right 表示考察的区间
[
left
,
right
]
[\textit{left},\textit{right}]
[left,right]。
right
\textit{right}
right 每向右移动一次,就统计一次进入区间的字符 x。为保证
cnt
\textit{cnt}
cnt 的值不为正,若此时
cnt
[
x
]
>
0
\textit{cnt}[x]>0
cnt[x]>0,则向右移动左指针,减少离开区间的字符的
cnt
\textit{cnt}
cnt 值直到
cnt
[
x
]
≤
0
\textit{cnt}[x] \le 0
cnt[x]≤0。
注意到
[
left
,
right
]
[\textit{left},\textit{right}]
[left,right] 的长度每增加 1,
cnt
\textit{cnt}
cnt 的元素值之和就增加 1。当
[
left
,
right
]
[\textit{left},\textit{right}]
[left,right] 的长度恰好为 n 时,就意味着
cnt
\textit{cnt}
cnt 的元素值之和为 0。由于
cnt
\textit{cnt}
cnt 的值不为正,元素值之和为 0 就意味着所有元素均为 0,这样我们就找到了一个目标子串。
代码
class Solution {
public:
bool checkInclusion(string s1, string s2) {
int len1 = s1.size(), len2 = s2.size();
if(len1 > len2) return false;
vector<int> cnt(26);
for(int i = 0; i < len1; i++)
cnt[s1[i] - 97]--;
int left = 0;
for(int right = 0; right < len2; right++)
{
int x = s2[right] - 97;
cnt[x]++;
while(cnt[x] > 0)
{
cnt[s2[left] - 97]--;
left++;
}
if(right - left + 1 == len1)
return true;
}
return false;
}
};
复杂度分析
- 时间复杂度:O( n + m + ∣ Σ ∣ n+m+|\Sigma| n+m+∣Σ∣)。
- 空间复杂度:O( ∣ Σ ∣ |\Sigma| ∣Σ∣)。