文章目录
- 1.问题描述
- 2.难度等级
- 3.热门指数
- 4.解题思路
-
- 4.1 滑动窗口
- 4.2 双指针
- 参考文献
1.问题描述
给你两个字符串 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 和 s2 仅包含小写字母
2.难度等级
Medium。
3.热门指数
★★★★☆
出题公司:腾讯、富途。
4.解题思路
4.1 滑动窗口
由于排列不会改变字符串中每个字符的个数,所以只有当两个字符串每个字符的个数均相等时,一个字符串才是另一个字符串的排列。
根据这一性质,统计 s1 的字符个数,然后使用滑动窗口遍历 s2,统计窗口内字符个数是否和 s1 的相等。
如果相等,那么 s2 包含 s1 的排列之一,返回 true。
如果遍历完 s2 仍未找到 s1 的排列之一,返回 false。
注意,因为字符仅包含 26 个小写字母,所以统计字符个数可以使用一个长度为 26 的数组,数组下标与 26 个小写字母一一对应。
时间复杂度: O(m+n),其中 m 为 s1 长度,n 为 s2 长度。
空间复杂度: O(),其中 是字符集字符数,这道题中的字符集是小写字母,所以 为服务器托管网 26。
下面以 Go 为例给出实现。
func checkInclusion(s1 string, s2 string) bool {
m, n := len(s1), len(s2)
if m > n {
return false
}
var cnt1, cnt2 [26]int
for i, ch := range s1 {
cnt1[ch-'a']++
cnt2[s2[i]-'a']++
}
if cnt1 == cnt2 {
return true
}
for i := m; i n; i++ {
cnt2[s2[i]-'a']++
cnt2[s2[i-m]-'a']--
if cnt1 == cnt2 {
return true
}
}
return false
}
4.2 双指针
滑动窗口的思路是统计滑动窗口内 s2 的字符数量是否 s1 的相等。
我们也可以反过来,先统计 s1 的字符个数(使服务器托管网用减法),再去考察 s2 是否存在一个区间,其长度恰好为 len(s1),使得其字符个数(使用加法)为零。
在 s2 寻找区间时,可以使用双指针。
第一步:右指针移动,使字符个数加 1。
第二步:
1)如果右指针所指字符个数小于 0 则继续移动右指针。
2)如果字符个数等于 0,则判断双指针构成的区间长度是否为 len(s1),等于则找到,不等于则继续移动右指针。
3)如果字符个数大于 0,则移动左指针,直至字符个数等于零。
时间复杂度: O(m+n),其中 m 为 s1 长度,n 为 s2 长度。
空间复杂度: O(),其中 是字符集字符数,这道题中的字符集是小写字母,所以 为 26。
func checkInclusion(s1 string, s2 string) bool {
m, n := len(s1), len(s2)
if m > n {
return false
}
var cnt [26]int
for _, c := range s1 {
cnt[c-'a']--
}
left := 0
for right, c := range s2 {
x := c - 'a'
cnt[x]++
for cnt[x] > 0 {
cnt[s2[left]-'a']--
left++
}
if right-left+1 == m {
return true
}
}
return false
}
参考文献
567.字符串的排列 – LeetCode
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
相关推荐: Apache SeaTunnel 及 Web 功能部署指南(小白版)
在大数据处理领域,Apache SeaTunnel 已成为一款备受青睐的开源数据集成平台,它不仅可以基于Apache Spark和Flink,而且还有社区单独开发专属数据集成的Zeta引擎,提供了强大的数据处理能力。随着SeaTunnel Web的推出,用户界…