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".

这道题给了我们两个字符串s和p,让在s中找字符串p的所有变位次的位置,所谓变位次就是字符种类个数均相同但是顺序可以不同的两个词,那么肯定首先就要统计字符串p中字符出现的次数,然后从s的开头开始,每次找p字符串长度个字符,来验证字符个数是否相同,如果不相同出现了直接 break,如果一直都相同了,则将起始位置加入结果 res 中,参见代码如下:

解法一:

class Solution {
public:
vector<int> findAnagrams(string s, string p) {
if (s.empty()) return {};
vector<int> res, cnt(, );
int ns = s.size(), np = p.size(), i = ;
for (char c : p) ++cnt[c];
while (i < ns) {
bool success = true;
vector<int> tmp = cnt;
for (int j = i; j < i + np; ++j) {
if (--tmp[s[j]] < ) {
success = false;
break;
}
}
if (success) {
res.push_back(i);
}
++i;
}
return res;
}
};

我们可以将上述代码写的更加简洁一些,用两个哈希表,分别记录p的字符个数,和s中前p字符串长度的字符个数,然后比较,如果两者相同,则将0加入结果 res 中,然后开始遍历s中剩余的字符,每次右边加入一个新的字符,然后去掉左边的一个旧的字符,每次再比较两个哈希表是否相同即可,参见代码如下:

解法二:

class Solution {
public:
vector<int> findAnagrams(string s, string p) {
if (s.empty()) return {};
vector<int> res, m1(, ), m2(, );
for (int i = ; i < p.size(); ++i) {
++m1[s[i]]; ++m2[p[i]];
}
if (m1 == m2) res.push_back();
for (int i = p.size(); i < s.size(); ++i) {
++m1[s[i]];
--m1[s[i - p.size()]];
if (m1 == m2) res.push_back(i - p.size() + );
}
return res;
}
};

下面这种利用滑动窗口 Sliding Window 的方法也比较巧妙,首先统计字符串p的字符个数,然后用两个变量 left 和 right 表示滑动窗口的左右边界,用变量 cnt 表示字符串p中需要匹配的字符个数,然后开始循环,如果右边界的字符已经在哈希表中了,说明该字符在p中有出现,则 cnt 自减1,然后哈希表中该字符个数自减1,右边界自加1,如果此时 cnt 减为0了,说明p中的字符都匹配上了,那么将此时左边界加入结果 res 中。如果此时 right 和 left 的差为p的长度,说明此时应该去掉最左边的一个字符,如果该字符在哈希表中的个数大于等于0,说明该字符是p中的字符,为啥呢,因为上面有让每个字符自减1,如果不是p中的字符,那么在哈希表中个数应该为0,自减1后就为 -1,所以这样就知道该字符是否属于p,如果去掉了属于p的一个字符,cnt 自增1,参见代码如下:

解法三:

class Solution {
public:
vector<int> findAnagrams(string s, string p) {
if (s.empty()) return {};
vector<int> res, m(, );
int left = , right = , cnt = p.size(), n = s.size();
for (char c : p) ++m[c];
while (right < n) {
if (m[s[right++]]-- >= ) --cnt;
if (cnt == ) res.push_back(left);
if (right - left == p.size() && m[s[left++]]++ >= ) ++cnt;
}
return res;
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/438

类似题目:

Valid Anagram

Anagrams

参考资料:

https://leetcode.com/problems/find-all-anagrams-in-a-string/

https://leetcode.com/problems/find-all-anagrams-in-a-string/discuss/92015/ShortestConcise-JAVA-O(n)-Sliding-Window-Solution

https://leetcode.com/problems/find-all-anagrams-in-a-string/discuss/92027/c-on-sliding-window-concise-solution-with-explanation

https://leetcode.com/problems/find-all-anagrams-in-a-string/discuss/92007/Sliding-Window-algorithm-template-to-solve-all-the-Leetcode-substring-search-problem.

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Find All Anagrams in a String 找出字符串中所有的变位词的更多相关文章

  1. [LeetCode] 438. Find All Anagrams in a String 找出字符串中所有的变位词

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

  2. 【easy】438.Find All Anagrams in a String 找出字符串中所有的变位词

    Input: s: "abab" p: "ab" Output: [0, 1, 2] Explanation: The substring with start ...

  3. 438 Find All Anagrams in a String 找出字符串中所有的变位词

    详见:https://leetcode.com/problems/find-all-anagrams-in-a-string/description/ C++: class Solution { pu ...

  4. [LeetCode] 186. Reverse Words in a String II 翻转字符串中的单词 II

    Given an input string, reverse the string word by word. A word is defined as a sequence of non-space ...

  5. [LeetCode] 557. Reverse Words in a String III 翻转字符串中的单词 III

    Given a string, you need to reverse the order of characters in each word within a sentence while sti ...

  6. 剑指Offer 找出字符串中第一个只出现一次的字符

    题目描述 找出字符串中第一个只出现一次的字符 如果无此字符 请输出'.' 输入描述: 输入一串字符,由小写字母组成 输出描述: 输出一个字符 输入例子: asdfasdfo 输出例子: o 思路:数组 ...

  7. 找出字符串中第一个不重复的字符(JavaScript实现)

    如题~ 此算法仅供参考,小菜基本不懂高深的算法,只能用最朴实的思想去表达. //找出字符串中第一个不重复的字符 // firstUniqueChar("vdctdvc"); --& ...

  8. [leetcode/lintcode 题解] 谷歌面试题:找出有向图中的弱连通分量

    请找出有向图中弱连通分量.图中的每个节点包含 1 个标签和1 个相邻节点列表.(有向图的弱连通分量是任意两点均有有向边相连的极大子图) 将连通分量内的元素升序排列. 在线评测地址:https://ww ...

  9. LeetCode 438. Find All Anagrams in a String (在字符串中找到所有的变位词)

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

随机推荐

  1. 设置eclipse中自动添加get,set的注释为字段属性的注释

    一:说明 首先具体来看一下是什么效果,上图可能会更清楚一点 就是在get/set中自动加上属性的注释,那我们要怎么配置呢? 二:配置 2.1:下载附件 下载附件 2.2:替换class 原生的ecli ...

  2. 怎么调试lua性能

    怎么调试lua性能 我们的游戏使用的是Cocos2dx-lua 3.9的项目,最近发现我们的游戏.运行比较缓慢.想做一次性能优化了.其实主要分为GPU.CPU的分别优化.GPU部分的优化.网上有很多优 ...

  3. JavaWeb_day01_HTTP_Servlet

    本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! JavaWeb_day01 HTTP协议 HTTP(H ...

  4. FastDFS 安装及使用

    FastDFS 安装及使用 2012-11-17 13:10:31|  分类: Linux|举报|字号 订阅     Google了一下,流行的开源分布式文件系统有很多,介绍如下:   mogileF ...

  5. poi读取excel模板,填充内容并导出,支持导出2007支持公式自动计算

    /** * 版权所有(C) 2016 * @author www.xiongge.club * @date 2016-12-7 上午10:03:29 */ package xlsx; /** * @C ...

  6. iscroll5实现一个下拉刷新上拉加载的效果

    直接上代码!!! <!DOCTYPE html><html><head lang="en"> <meta charset="UT ...

  7. 深入理解javascript选择器API系列第三篇——h5新增的3种selector方法

    × 目录 [1]方法 [2]非实时 [3]缺陷 前面的话 尽管DOM作为API已经非常完善了,但是为了实现更多的功能,DOM仍然进行了扩展,其中一个重要的扩展就是对选择器API的扩展.人们对jQuer ...

  8. 深入理解SQL注入绕过WAF和过滤机制

    知己知彼,百战不殆 --孙子兵法 [目录] 0x0 前言 0x1 WAF的常见特征 0x2 绕过WAF的方法 0x3 SQLi Filter的实现及Evasion 0x4 延伸及测试向量示例 0x5 ...

  9. javascript中需要自行定义的函数

    1.toString()与String() 使用方式:x.toString();-----String(x); String是万能的方法,而x.toString()则有局限性,无法将undefined ...

  10. http参数的封装(后台接受参数的场景)

    场景 不管是任何web框架作为一个web的开发人员必须要搞明白control层如何接受各种参数. 下面就根据我们公司的系统架构(nutz)来进行一下场景描述.各位小伙伴也可以根据这些 场景自己去总结一 ...