leetcode567. 字符串的排列
题目描述
链接: leetcode567.
给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。
换句话说,s1 的排列之一是 s2 的 子串 。
示例1:
输入:s1 = "ab" s2 = "eidbaooo"
输出:true
解释:s2 包含 s1 的排列之一 ("ba").
示例2:
输入:s1= "ab" s2 = "eidboaoo" 输出:false
题解
滑动窗口:
(1)window维护s1各个字符出现的次数
(2)滑动窗口内每一个右边界字符进入窗口后,将该字符频数-1
(3)如果某个字符频数变成负值,即出现次数多了,开始尝试下一个左端点,left++,窗口右移
(4)左边界字符出窗口后,该左边界字符出现次数要重新+1
- java解法
public boolean checkInclusion(String s1, String s2) {
if (s1.length() > s2.length()) {
return false;
}
Map<Character, Integer> window = new HashMap<>(); // 存储s1中各个字符出现的差值
for (int i = 0; i < s1.length(); ++i) { // 初始化为s1中该字符出现的次数
window.put(s1.charAt(i), window.getOrDefault(s1.charAt(i), 0) + 1);
}
int left = 0;
int right = 0;
while (right < s2.length()) {
Character ch = s2.charAt(right++);
window.computeIfPresent(ch, (k,v) -> v-1);
while (left < right && (!window.containsKey(ch) || window.get(ch) < 0)) { // 当s2中该字符出现次数超了,窗口右移
window.computeIfPresent(s2.charAt(left++), (k,v) -> v+1);
}
if (right - left == s1.length()) {
return true;
}
}
return false;
}
- golang解法
func checkInclusion(s1 string, s2 string) bool {
window := map[byte]int{}
left, right := 0, 0
for i := 0; i < len(s1); i++ {
window[s1[i]]++
}
for right < len(s2) {
ch := s2[right]
window[ch]--
right++
for left < right && window[ch] < 0 {
window[s2[left]]++
left++
}
if right - left == len(s1) {
return true
}
}
return false
}