解题思路:

这道题一个最重要的难点就是时间控制。另一个就是哈希表的应用。

笔者第一次是从s中逐步截取与p等长的子串m,然后再暴力遍历分析m和p是否为Anagrams(只有字符顺序不同的两个字符串),总的时间复杂度为O(s*p*p)大概是O(n^3),自然不能通过。第二次时间优化是在比较m和p时,采用《如何判断两个String是否是Anagrams》一文中介绍的方法,总的时间复杂度是O(s*p),大概是O(n^2),然后依然没有通过,超时。

最后一次进一步优化,使用滑动窗口,使得时间复杂度为为O(n),这就是算法的力量!

算法介绍:

(1)NumberOfDeference = p.length(),用来表示目前窗口中的字符和p的差异度(由于窗口最大时(为p.length())才有可能使NumberOfDeference为0,所以NumberOfDeference 为0时窗口中与p为Anagrams)。NumberOfDeference差异度的含义:一开始窗口左右指针都指向第一个,所以差异度最大为p.length();当窗口中进来一个p中有的字符,差异度就减一,出去一个有的差异度就增一;至于进来或出去的是p中没有的则NumberOfDeference不变,反正窗口的最大值也不过是p.length()。

(2)窗口的左右两个指针:left和right,分别指向窗口的左端和右端。

滑动窗口具体操作:

先滑动右指针,

1.1 加进来的字符如果该字符在数组asciiChars的计数中非负,则NumberOfDeference减一,否则不做操作,

1.2无论在不在数组asciiChars该字符相应位置计数都减一

1.3如果滑动完right,判断如果窗口长度到达p.length()(如果长度到达p.length(),并且NumberOfDeference为0,则将此时的left值加入到result中),滑动左窗口。

滑动左指针:

2.1被踢出窗口的那个字符如果在数组asciiChars的计数中非负,则NumberOfDeference增一,不在则不做操作。

2.2无论在不在数组asciiChars该字符相应位置计数都加一

(3)上面1.1和2.1操作的原理:asciiChars中的记录的数据是代表p中含有的的每个字符的数量去掉当前窗口中存在的p字符串中每个字符的数量,一开始窗口大小为0,啥都不存在,自然asciiChars中记录的就是全部p中含有的的每个字符的数量,如果窗口中有一个,则asciiChars相应的记录中就少一个。如果窗口中多包含一个p中没有的(或者包含的某一个字符的数量比p中有的还多),那么这时候,asciiChars中相应的记录值就会变成负数,代表当前窗口中包含相应字符的“多余”的数量。

所以当进来一个的时候,如果相应记录为非负,那么这个进入是有意义的,则差异度(NumberOfDeference)减一;当出去一个的时候,如果相应记录为非负,那么这个出去是有意义的,则差异度(NumberOfDeference)加一。

(4)asciiChars用到哈希表思想,用来记录p中每一种字符分别有多少个。详见《如何判断两个String是否是Anagrams》一文。

阅读源代码并分析:::真是有好多看不懂的地方( ⊙ o ⊙ )

public static List<Integer> findAnagrams(String s, String p) {List<Integer> result = new ArrayList<Integer>();int NumberOfDeference = p.length(); //差异度指数 int left=0,right=0; //窗口左右指针 int[] asciiChars = new int[256]; //记录p中字符有哪些及其数量的数组 for (int i = p.length() - 1; i>=0; --i) { ++asciiChars[p.charAt(i)]; } //记录完毕 p.charAt(i)返回的是字符串中i对应的索引处的字符 是char类型 for(;right<s.length();right++){ //滑动右窗口 asciiChars[s.charAt(right)]--; //在该字符相应位置减一 if(asciiChars[s.charAt(right)]>=0) NumberOfDeference--; //如果加进来的那个在p中,NumberOfDeference减一 if(right-left == (p.length()-1)){ //如果这时窗口大小为p.length() if(NumberOfDeference==0) result.add(left); //这时出现一次匹配,将左窗口加到result中 //下面是滑动左窗口的操作 if(asciiChars[s.charAt(left)]>=0) { NumberOfDeference++; //如果被踢出的那个在p中,NumberOfDeference加一  } asciiChars[s.charAt(left)]++; //数组中相应字符计数位置加回来 left++; //左窗口向右滑动  } } return result; }

转载于:https://www.cnblogs.com/maowuyu-xb/p/6764188.html

FindAllAnagramsinaString相关推荐

  1. Leetcode双指针滑动窗口相关题目

    滑动窗口 滑动窗口解决哪种问题? 滑动窗口解决给定两个字符串S和T,问你S中是否存在一个子串,包含T中的所有字符并且不含有其他字符. 窗口右指针向右移动,窗口增大,直到满足条件,这时候找到可行解. 窗 ...

  2. 找到字符串中所有字母异位词—leetcode438

    给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引. 字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100. 说明: ...

  3. 哈希表-set/数组

    在C++中,set 和 map 分别提供以下三种数据结构,其底层实现以及优劣如下表所示 参考:https://programmercarl.com/%E5%93%88%E5%B8%8C%E8%A1%A ...

  4. leetcode 438. Find All Anagrams in a String | 438. 找到字符串中所有字母异位词(Java)

    题目 https://leetcode.com/problems/find-all-anagrams-in-a-string/ 题解 方法1:尝试构造一种"与顺序无关的哈希" 思考 ...

  5. 【解题报告】Leecode 438. 找到字符串中所有字母异位词——Leecode每日一题系列

    今天是坚持每日一题打卡的第二十七天 题目链接:https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/ 题解汇总:https:// ...

  6. leetcode 滑动窗口小结 (一)

    目录 小结以及代码框架 76. 最小覆盖子串 滑动窗口 代码以及注释 567. 字符串的排列 滑动窗口 438. 找到字符串中所有字母异位词 3. 无重复字符的最长子串 化简框架 reference ...

  7. LeetCode 438. 找到字符串中所有字母异位词(滑动窗口)

    1. 题目 给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引. 字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100 ...

  8. LeetCode 热题 HOT 100 完整题解笔记知识点分类 C++代码实现

    1.知识点分布 填一下这个之前欠的天坑,复习一下算法入门的经典基础题. 除夕,正月初一,初二,一共写了三整天,除了吃饭就窝着补题. 每天30题+,整个人都写晕啦,终于写完啦() markdown生成 ...

  9. leetcode-滑动窗口(双指针-代码有套路-附总结代码)总结-满足条件-破坏条件(76,438,3,209有模板(别人总结的很好,学习一波))

    滑动窗口:(其实可以理解为双指针) 参考自原作者链接:https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/solution/h ...

最新文章

  1. 【翻译】SQL Server索引进阶:第七级,过滤的索引
  2. 提交代码,SVN被锁定,提示:svn is already locked解决方案
  3. 网络推广外包浅析当下网站优化处于健康状态有利于网络推广外包
  4. python中返回上一步操作的代码_Pycharm代码跳转后退回操作详解
  5. Linux进程状态解析 之 R、S、D、T、Z、X (主要有三个状态)
  6. vsftpd + Berkeley DB 创建基于虚拟用户的FTP
  7. 贝索斯前妻再捐2.81亿美元
  8. YOLOv4/v5的创新点汇总!
  9. Mac里的airdrop传输文件
  10. 使用晨曦记账本记账,将账目明细导出excel表格上
  11. 运用类似于沙盘模拟的方式熟悉业务
  12. 信息学奥赛一本通C++版
  13. Scratch编程入门-画图模块1【认识画图模块积木】
  14. Leetcode-1436: 旅行终点站(6行简单解法)
  15. otl连接mysql数据库_C++类库:OTL连接MySQL ODBC数据库(insert, update, select)
  16. Android 自启项管理器工具
  17. WINDOWS文件夹下的应用程序
  18. 经典Seq2Seq与注意力Seq2Seq模型结构详解
  19. 华硕电脑笔记本台式机预装专用系统 V2011
  20. Iar工程编译和下载的使用教程

热门文章

  1. 这 6 个 SpringBoot 项目够经典!
  2. Java笔试面试总结—try、catch、finally语句中有return 的各类情况
  3. 蚂蚁开源增强版 SpringBoot,都有哪些骚能力?
  4. 你会不会模拟超过 5 万用户的并发访问?
  5. 聊一聊Java 泛型中的通配符 T,E,K,V,?
  6. 清华大学唐杰教授:人工智能的十年总结
  7. 炼个BERT别人花几分钟你花了快1天?谷歌:我这是4810亿参数的巨型BERT
  8. NumPy迎来重大版本更新
  9. CVPR 2020 Oral | 旷视提出Circle Loss,革新深度特征学习范式
  10. 卷积神经网络中十大拍案叫绝的操作!