Find All Anagrams in a String

Find All Anagrams in a String (window sliding alg)

update Jun 29, 2017

leetcodearrow-up-right Given a string s and a non-empty string p, find all the start indices of p's anagrams in s.

Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 20,100.

The order of output does not matter.

Example 1:

    Input:
    s: "cbaebabacd" p: "abc"

    Output:
    [0, 6]

    Explanation:
    The substring with start index = 0 is "cba", which is an anagram of "abc".
    The substring with start index = 6 is "bac", which is an anagram of "abc".

Example 2:

    Input:
    s: "abab" p: "ab"

    Output:
    [0, 1, 2]

    Explanation:
    The substring with start index = 0 is "ab", which is an anagram of "ab".
    The substring with start index = 1 is "ba", which is an anagram of "ab".
    The substring with start index = 2 is "ab", which is an anagram of "ab".

思路

最简单的方法就是把pattern string的char进行统计,建counting map,然后brute force,但是这样做的速度太慢。一个优化的方法是使用 sliding window algorithm ,也就是 maintain 一个长度等于len(pattern)的 window, 每次向右移动一格,统计进入和离开 window的char,用一个 int need变量记录当前还需要match的char数量,如果need==0,则说明找到一个subString。

这里arrow-up-right 是一个很棒的分析,有提供window slide解决substring问题的模板。

Java code:

Python code:

上面的java实现采用的操作顺序是 移动right -- check need -- 移动left,下面的python实现采用 移动right -- 移动left -- check need,感觉更好理解。

这里的need其实就是九章中所讲的 “需要的字母数量减去window中相应字母数量的table的绝对值和”,维持这个need,就可以做到O(1)时间内更新因为移动window造成的所有变化。

Contains Duplicate IIarrow-up-right这道题也可以用window sliding的方法做,可以结合在一起。

update Jan 27,2018 20:08

Update: 更新最新的 sliding window 写法

每层外循环开始时,先用一个while循环判断是否需要移动right,保证该循环结束之后,window size 是符合要求的 ,然后做事情,最后右移left;另外,为了一开始的时候可以初始化第一个位置,可以令 right 初始化为 -1;

  • Java Code:

update May 8,2018 23:24

C++ Code

更新一个C++的解法,和上面的Java解法基本思路是一致的,不同之处在于采用直接return的方法跳出循环。