题目
- 找到字符串中所有字母异位词
题目描述
给定一个字符串 s 和一个非空字符串p,找到s中所有是p的字母异位词的子串,返回这些子串的起始索引。
字符串只包含小写英文字母,并且字符串s和p的长度都不超过20100。
说明
字母异位词指字母相同,但排列不同的字符串。
不考虑答案输出的顺序。
案例
示例1
输入:
s: "cbaebabacd" p: "abc"
输出:
[0, 6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的字母异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的字母异位词。
示例2
输入:
s: "abab" p: "ab"
输出:
[0, 1, 2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的字母异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的字母异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的字母异位词。
思路
框架
/* 滑动窗口算法框架 */
void slidingWindow(string s, string t) {
unordered_map<char, int> need, window;
// 初始化字串所有元素的个数
for (char c : t) need[c]++;
// 初始化左右指针
int left = 0, right = 0;
// 有效性的个数
int valid = 0;
while (right < s.size()) {
// c 是将移入窗口的字符
char c = s[right];
// 右移窗口
right++;
// 进行窗口内数据的一系列更新
...
/*** debug 输出的位置 ***/
printf("window: [%d, %d)\n", left, right);
/********************/
// 判断左侧窗口是否要收缩
while (window needs shrink) {
// d 是将移出窗口的字符
char d = s[left];
// 左移窗口
left++;
// 进行窗口内数据的一系列更新
...
}
}
}
代码
package leetcode
// findAnagrams
// 438. 找到字符串中所有字母异位词
func findAnagrams(s, p string) []int {
// 初始化计数器,分别记录【窗口】中字符的出现次数和T中字符串出现次数
window := map[byte]int{}
need := map[byte]int{}
for i := 0; i < len(p); i++ {
cur := p[i]
need[cur]++
}
// 初始化窗口的两端,区间[left, right)
left, right := 0, 0
// 表示窗口中满足need条件的字符个数
// 如果valid和len(need)的大小相同,则说明窗口已满足条件,已经完全覆盖了字符串t
valid := 0
// 保存结果
data := []int{}
// 结束条件:存在满足条件的节点即可
for right < len(s) {
// 即将移入窗口的值
cur := s[right]
right++
// 进行窗口数据更新
// 首先校验是否在T串
if _, ok := need[cur]; ok {
window[cur]++
// 表示窗口中满足need条件的字符个数
if window[cur] == need[cur] {
valid++
}
}
// 判断窗口是否需要收缩:窗口大小大于len(need)时,应为排列,显然长度应该是一样的。
for (right - left) >= len(p) {
// 结束条件:在这里判断是否找到了合法的子串,如果合法则将左指针存入结果中
if valid == len(need){
data = append(data, left)
}
// 将移出窗口的字符
delS := s[left]
left++
if _, ok := need[delS]; ok {
// 既要移除窗口的值,也要移除验证的值
if window[delS] == need[delS] {
valid--
}
window[delS]--
}
}
}
return data
}
同类
算法—leetcode—567—字符串的排列
算法—leetcode—76—最小覆盖子串
参考
来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/fi…
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。