给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。
换句话说,第一个字符串的排列之一是第二个字符串的子串。
示例1:
输入: s1 = "ab" s2 = "eidbaooo"
输出: True
解释: s2 包含 s1 的排列之一 ("ba").
示例2:
输入: s1= "ab" s2 = "eidboaoo"
输出: False
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/permutation-in-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
感谢labuladong大神,传送门我写了套框架,把滑动窗口算法变成了默写题。
class Solution {
public boolean checkInclusion(String s1, String s2) {
if (s1 == null || s1.length() == 0) return true;
if (s2 == null || s2.length() == 0) return false;
// return checkInclusionI(s1, s2);
return checkInclusionII(s1, s2);
}
//方法二:使用数组保存字符串s1和s2中字符出现的次数
//时间复杂度O(mn),空间复杂度O(1)
private boolean checkInclusionII(String s1, String s2) {
int[] need = new int[256];
int[] window = new int[256];
for (char c : s1.toCharArray()) {
need[c]++;
}
int left = 0, right = 0;
//统计窗口中满足字符串s1中字符的个数
int valid = 0;
char[] str = s2.toCharArray();
while (right < str.length) {
char c = str[right];
right++;
window[c]++;
//当窗口中字符个数满足s1字符个数时,valid加1
if (need[c] > 0 && need[c] >= window[c]) {
valid++;
}
//收缩窗口
while (right - left >= s1.length()) {
//收缩窗口时判断s2是否包含s1的排列
if (valid == s1.length()) {
return true;
}
char d = str[left];
left++;
//更新窗口数据
if (need[d] > 0 && need[d] >= window[d]) {
valid--;
}
//收缩窗口,窗口中字符个数减1
window[d]--;
}
}
return false;
}
//方法一:定义两个Map分别保存字符串s1和s2中字符出现的次数
//时间复杂度O(mn),m为s1字符个数,n为s2字符个数
//空间复杂度O(m)
private boolean checkInclusionI(String s1, String s2) {
Map<Character, Integer> need = new HashMap<>();
Map<Character, Integer> window = new HashMap<>();
for (char c : s1.toCharArray()) {
need.put(c, need.getOrDefault(c, 0) + 1);
}
int left = 0, right = 0;
//统计窗口中满足字符串s1中字符的个数
int valid = 0;
char[] str = s2.toCharArray();
while (right < str.length) {
char c = str[right];
right++;
//更新窗口数据
if (need.containsKey(c)) {
window.put(c, window.getOrDefault(c, 0) + 1);
//当窗口中字符个数满足s1字符个数时,valid加1
if (window.get(c).equals(need.get(c))) {
valid++;
}
}
//收缩窗口
while (right - left >= s1.length()) {
//收缩窗口时判断s2是否包含s1的排列
if (valid == need.size()) {
return true;
}
char d = str[left];
left++;
//更新窗口数据
if (need.containsKey(d)) {
//窗口收缩时判断是否满足条件
if (window.get(d).equals(need.get(d))) {
valid--;
}
//收缩窗口,窗口中字符个数减1
window.put(d, window.get(d) - 1);
}
}
}
return false;
}
}