题目链接:https://leetcode.com/problems/permutation-in-string/
给定字符串s1、s2,判断s2中是否存在一个子串,是s1的一个组合。
提到字符串的组合,首先想到的就是map,key是字符,value是字符出现的次数。
问题就转为在s2中寻找一个子串对应这个map。
这是一种解题思路,但是代码会有点复杂。
这里给出一个更简单的思路。
首先,满足条件的子串,它的长度和s1一定是一样的。
其次,就用上了抵消的思想。
这个子串和s1是可以相互抵消的。
看下代码
func checkInclusion(s1 string, s2 string) bool {
mp := make(map[uint8]int)
for i := 0; i < len(s1); i++ {
mp[s1[i]]++
}
var isMatch int
var start int
for end := 0; end < len(s2); end++ {
endChar := s2[end]
if _, ok := mp[endChar]; ok {
mp[endChar]--
if mp[endChar] == 0 {
isMatch++
}
}
if isMatch == len(mp) {
return true
}
if end >= len(s1) - 1 {
startChar := s2[start]
start++
if v, ok := mp[startChar]; ok {
if v == 0 {
isMatch--
}
mp[startChar]++
}
}
}
return false
}
这个代码还是很有技巧性的。
下面再给一个方便记忆的版本。
func checkInclusion(s1 string, s2 string) bool {
lth1 := len(s1)
lth2 := len(s2)
if lth1 > lth2 {
return false
}
mp1 := make(map[uint8]int)
for i := 0; i < lth1; i++ {
mp1[s1[i]]++
mp1[s2[i]]--
}
if isMapZero(mp1) {
return true
}
for i := lth1; i < lth2; i++ {
mp1[s2[i]]--
mp1[s2[i - lth1]]++
if isMapZero(mp1) {
return true
}
}
return false
}
func isMapZero(mp map[uint8]int) bool {
for _, v := range mp {
if v != 0 {
return false
}
}
return true
}
参考资料
https://github.com/Chanda-Abdul/Grokking-the-Coding-Interview-Patterns/blob/main/%E2%9C%85%20%20Pattern%2001%20:%20Sliding%20Window.md
https://leetcode.com/problems/permutation-in-string/discuss/102588/Java-Solution-Sliding-Window