LeetCode: Substring with Concatenation of All Words 解题报告
Substring with Concatenation of All Words
You are given a string, S, and a list of words, L, that are all of the same length. Find all starting indices of substring(s) in S that is a concatenation of each word in L exactly once and without any intervening characters.
For example, given:
S: "barfoothefoobarman"
L: ["foo", "bar"]
You should return the indices: [0,9].
(order does not matter).
SOLUTION 1:
1. 使用HashMap来保存L中所有的字串。
2. 暴力破解之。使用i记录我们的查找结果字符串的位置,j记录单个单词的查找位置。j每次移动一个L中单词的位置。
3. 注意各种越界条件:i查到离结束还有L*N(L中所有单词总长)的时候,即需要停止。
j 也要考虑每一次查找的单词的长度。
4. 使用第二个HashMap来记录我们查到的单词。如果所有的单词都查到了,即可记录一个解。
// SOLUTION 1:
public List<Integer> findSubstring1(String S, String[] L) {
HashMap<String, Integer> map = new HashMap<String, Integer>();
HashMap<String, Integer> found = new HashMap<String, Integer>();
List<Integer> ret = new ArrayList<Integer>(); if (S == null || L == null || L.length == 0) {
return ret;
} int cntL = 0; // put all the strings into the map.
for (String s: L) {
if (map.containsKey(s)) {
map.put(s, map.get(s) + 1);
} else {
map.put(s, 1);
cntL++;
}
} int lenL = L[0].length(); int cntFound = 0; // 注意这里的条件:i < S.length() - lenL * L.length
// 这里很关键,如果长度不够了,不需要再继续查找
for (int i = 0; i <= S.length() - lenL * L.length; i++) {
// clear the found hashmap.
found.clear();
cntFound = 0; // 一次前进一个L的length.
// 注意j <= S.length() - lenL; 防止越界
for (int j = i; j <= S.length() - lenL; j += lenL) {
String sub = S.substring(j, j + lenL);
if (map.containsKey(sub)) {
if (found.containsKey(sub)) {
if (found.get(sub) == map.get(sub)) {
// 超过了限制数目
break;
} found.put(sub, found.get(sub) + 1);
} else {
found.put(sub, 1);
} if (found.get(sub) == map.get(sub)) {
cntFound++;
} // L中所有的字符串都已经找到了。
if (cntFound == cntL) {
ret.add(i);
}
} else {
// 不符合条件,可以break,i前进到下一个匹配位置
break;
}
}
} return ret;
}
12.26.2014 redo:
注意到几个容易出错的点:1. i的终止条件(用以防止TLE). 2. j的终止条件。
public class Solution {
public List<Integer> findSubstring(String S, String[] L) {
ArrayList<Integer> ret = new ArrayList<Integer>();
if (S == null || L == null || L.length == 0) {
return ret;
} HashMap<String, Integer> map = new HashMap<String, Integer>();
HashMap<String, Integer> des = new HashMap<String, Integer>(); for (String s: L) {
if (map.containsKey(s)) {
map.put(s, map.get(s) + 1);
} else {
// bug 1: should be , not .
map.put(s, 1);
}
} int wordLen = L[0].length(); int size = L.length;
int cnt = 0; int len = S.length();
// bug 3: j <= len - wordLen * size to avoid the TLE
for (int i = 0; i <= len - wordLen * size; i++) {
// bug 2: should be des.clear not map.clear.
des.clear();
cnt = 0; // pay attention: should use j <= len.
for (int j = i; j <= len - wordLen; j += wordLen) {
String sub = S.substring(j, j + wordLen); if (!map.containsKey(sub)) {
break;
} if (des.containsKey(sub)) {
des.put(sub, 1 + des.get(sub));
} else {
des.put(sub, 1);
} if (des.get(sub) > map.get(sub)) {
break;
} cnt++; if (cnt == size) {
ret.add(i);
break;
}
}
} return ret;
}
}
SOLUTION 2:
1. 与解1相比,我们这次每次复制一个HashMap,找到一个单词,即减少此单词的计数,直到HashMap为空,表示我们找到一个解。
与Solution 1相比,这个方法写起来会简单一点。
// SOLUTION 2:
public List<Integer> findSubstring(String S, String[] L) {
HashMap<String, Integer> map = new HashMap<String, Integer>();
HashMap<String, Integer> found;
List<Integer> ret = new ArrayList<Integer>(); if (S == null || L == null || L.length == 0) {
return ret;
} // put all the strings into the map.
for (String s: L) {
if (map.containsKey(s)) {
map.put(s, map.get(s) + 1);
} else {
map.put(s, 1);
}
} int lenL = L[0].length(); // 注意这里的条件:i < S.length() - lenL * L.length
// 这里很关键,如果长度不够了,不需要再继续查找
for (int i = 0; i <= S.length() - lenL * L.length; i++) {
// 每一次,都复制之前的hashMap.
found = new HashMap<String, Integer>(map); // 一次前进一个L的length.
// 注意j <= S.length() - lenL; 防止越界
for (int j = i; j <= S.length() - lenL; j += lenL) {
String sub = S.substring(j, j + lenL);
if (found.containsKey(sub)) {
// 将找到字符串的计数器减1.
found.put(sub, found.get(sub) - 1); // 减到0即可将其移出。否则会产生重复运算,以及我们用MAP为空来判断是否找到所有的单词。
if (found.get(sub) == 0) {
found.remove(sub);
}
} else {
// 不符合条件,可以break,i前进到下一个匹配位置
break;
} // L中所有的字符串都已经找到了。
if (found.isEmpty()) {
ret.add(i);
}
}
} return ret;
}
SOLUTION 3:
九章算法官网解:
http://www.ninechapter.com/solutions/substring-with-concatenation-of-all-words/
主页君GITHUB:
https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/string/FindSubstring.java
LeetCode: Substring with Concatenation of All Words 解题报告的更多相关文章
- 【LeetCode】697. Degree of an Array 解题报告
[LeetCode]697. Degree of an Array 解题报告 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problems/degree- ...
- 【LeetCode】779. K-th Symbol in Grammar 解题报告(Python)
[LeetCode]779. K-th Symbol in Grammar 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingz ...
- 【LeetCode】792. Number of Matching Subsequences 解题报告(Python)
[LeetCode]792. Number of Matching Subsequences 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://f ...
- 【LeetCode】881. Boats to Save People 解题报告(Python)
[LeetCode]881. Boats to Save People 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu ...
- 【LeetCode】802. Find Eventual Safe States 解题报告(Python)
[LeetCode]802. Find Eventual Safe States 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemi ...
- 【LeetCode】813. Largest Sum of Averages 解题报告(Python)
[LeetCode]813. Largest Sum of Averages 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博 ...
- 【LeetCode】166. Fraction to Recurring Decimal 解题报告(Python)
[LeetCode]166. Fraction to Recurring Decimal 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingz ...
- 【LeetCode】556. Next Greater Element III 解题报告(Python)
[LeetCode]556. Next Greater Element III 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人 ...
- 【LeetCode】522. Longest Uncommon Subsequence II 解题报告(Python)
[LeetCode]522. Longest Uncommon Subsequence II 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemin ...
随机推荐
- vim插件之pathogen,NERDTree,Command-T,Powerline
pathogen 功能说明 一个插件包往往具备多种功能,每个文件根据Vim的路径约定会放置到不同的目录下,通用插件放到plugin下,语法高亮插件放到syntax下,自动加载插件放到autoload下 ...
- eclipse to avoid the message, disable the...
标题 CreateTime--2018年5月9日10:38:15 Author:Marydon 1.问题描述 2.问题解析 这是因为eclipse的智能提示超时引起的,将超时间调大即可,如:200 ...
- HTTP所承载的货物(图像、文本、软件等)要满足的条件
HTTP所承载的货物(图像.文本.软件等)要满足的条件: •可以被正确识别 通过Content-Type 首部说明媒体格式,Content-Language 说明语言,以便浏览器和其他客户端能正确处理 ...
- Oracle的PLSQL别名中文出现乱码解决方法
乱码之乱,乱在心里.行而上,眼迷茫! 01.查询oracle服务端默认语言 select * from nls_database_parameters NLS_LANGUAGE AMERICAN ...
- Java实现可视化迷宫
代码地址如下:http://www.demodashi.com/demo/14547.html 需求 使用深度优先算法求解迷宫路径,使用Java实现求解过程的可视化,可单步运行,形象直观. 演示效果 ...
- springmvc编码问题
web.xml中加入 <filter> <filter-name>encodingFilter</filter-name> <filter-class> ...
- Centos5 下redmine的安装及配置
Redmine: 这是基于ROR框架开发的一套跨平台项目管理系统,是项目管理系统的后起之秀,据说是源于Basecamp的ror版而来,支持多种数据库,除了和 DotProject的功能大致相当外,还有 ...
- 照片管家iOS-实现本地相册、视频、安全保护、社交分享源码下载Demo
<照片管家> APP功能: 1.本地照片批量导入与编辑 2.本地视频存储与播放 3.手势密码.数字密码.TouchID安全保护 4.QQ.微信.微博.空间社交分享 5.其他细节功能. 运用 ...
- [转]网易云音乐Android版使用的开源组件
原文链接 网易云音乐Android版从第一版使用到现在,全新的 Material Design 界面,更加清新.简洁.同样也是音乐播放器开发者,我们确实需要思考,相同的功能,会如何选择.感谢开源,让我 ...
- Python练习笔记——利用递归求年龄,第五个比第四个大2岁...
现在有五个人, 第五个人比第四个人大两岁,18 第四个人比第三个人大两岁,16 第三个人比第二个人大两岁,14 第二个人比第一个人大两岁,12 第一个人现10岁, 10 ...