leetcode_438_Find All Anagrams in a String_哈希表_java实现
题目:
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等长的子串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》一文。
代码:
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)]; } //记录完毕
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;
}
leetcode_438_Find All Anagrams in a String_哈希表_java实现的更多相关文章
- 【字符串哈希】【哈希表】Aizu - 1370 - Hidden Anagrams
给你两个4k长度的串,问你最长公共子串.两个子串相同被定义为所有字母的出现次数分别相同即可. 就枚举第一个串的所有子串,将字母出现的次数看作一个大数,进行哈希(双关键字),塞到哈希表里面.然后枚举第二 ...
- 算法与数据结构基础 - 哈希表(Hash Table)
Hash Table基础 哈希表(Hash Table)是常用的数据结构,其运用哈希函数(hash function)实现映射,内部使用开放定址.拉链法等方式解决哈希冲突,使得读写时间复杂度平均为O( ...
- C#LeetCode刷题-哈希表
哈希表篇 # 题名 刷题 通过率 难度 1 两数之和 C#LeetCode刷题之#1-两数之和(Two Sum) 42.8% 简单 3 无重复字符的最长子串 24.2% 中等 18 四数之和 ...
- [PHP内核探索]PHP中的哈希表
在PHP内核中,其中一个很重要的数据结构就是HashTable.我们常用的数组,在内核中就是用HashTable来实现.那么,PHP的HashTable是怎么实现的呢?最近在看HashTable的数据 ...
- Java 哈希表运用-LeetCode 1 Two Sum
Given an array of integers, find two numbers such that they add up to a specific target number. The ...
- ELF Format 笔记(十五)—— 符号哈希表
ilocker:关注 Android 安全(新手) QQ: 2597294287 符号哈希表用于支援符号表的访问,能够提高符号搜索速度. 下表用于解释该哈希表的组织,但该格式并不属于 ELF 规范. ...
- Java基础知识笔记(一:修饰词、向量、哈希表)
一.Java语言的特点(养成经常查看Java在线帮助文档的习惯) (1)简单性:Java语言是在C和C++计算机语言的基础上进行简化和改进的一种新型计算机语言.它去掉了C和C++最难正确应用的指针和最 ...
- 什么叫哈希表(Hash Table)
散列表(也叫哈希表),是根据关键码值直接进行访问的数据结构,也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录的数组叫做散列表. - 数据结构 ...
- 【哈希表】CodeVs1230元素查找
一.写在前面 哈希表(Hash Table),又称散列表,是一种可以快速处理插入和查询操作的数据结构.哈希表体现着函数映射的思想,它将数据与其存储位置通过某种函数联系起来,其在查询时的高效性也体现在这 ...
随机推荐
- (转) 关于在IE6下 无法跳转问题
之前在项目,用到超链接,在ie下没有问题,但是到了ie6,居然发现点击事件不起作用, 真不可思议,以前都没注意到,后来网上搜了下,问题就出在这个void(0)上!现把网上的资料整理了下. <a ...
- android 6.0 httpclient
Apache HTTP Client RemovalAndroid 6.0 release removes support for the Apache HTTP client. If your ap ...
- python-set集合类方法
s1=set([11,22,33,44,'Tom','tony',11,77,2.5,])返回的是{11,22,33,44,'Tom','tony',77,2.5}(注意:返回的并不是一个字典,只是告 ...
- www.97top10.com--做最好的技术交流网站
www.97top10.com--做最好的技术交流网站
- C# 分层 三层架构
Hello! 三层架构↓↓↓↓↓↓ 三层架构分为:表现层(UI(User Interface)).业务逻辑层(BLL(Business Logic Layer)).数据访问层(DAL(Data Acc ...
- C# Winform打包部署时添加注册表信息实现开机启动
使用VS自带的打包模块可以很方便的对项目进行打包部署,同时我们也可以在安装部署时操作注册表实现开机启动软件.具体实现如下: 1.添加安装部署项目后,鼠标右键安装项目->视图->注册表,HK ...
- CRM 2013 系统设置新功能二:Entity images 图像字段
CRM2013系统默认的许多实体都已经有了图像的选择,如 右上角可以设置当前用户的头像. 客户.联系人等都可以,下面将介绍一下此项新功能: 一.实体中新建图像字段,其中系统自动命名entityinag ...
- linux服务器如何设置目录权限,让开发只能在测试目录下开发,不在线上目录上开发
当一台服务器上,既有测试环境,也有生成的环境,开发需要在线上测试,如果开发生产环境的权限,那开发容易误操作 需求如下: (1)生产环境的代码,必须有专用的账号登陆进行管理 (2)开发测试环境的代码,开 ...
- Animated progress view with CAGradientLayer(带翻译)<待更新>
原文网址:使用CAGradientLayer的动画精度条View Modern software design is getting flatter and thinner all the time. ...
- UI交互设计的网站
1.http://www.xueui.cn/other-tutorials/ui-interaction-design.html 2.http://www.3lian.com/edu/2015/12- ...