hello,大家好,我是魔笑,今天给大家带来的是lettocde的30题。
今天唠叨一下自己写博客的目的:
我写博客,也是在记录自己学习的每一道题,和自己学习的东西,为什么要写博客,我的想法是,虽然经常学习,但是,如果不记下来,过段时间,就遗忘了。我之前也学了很多东西,但是过段时间有点记不清了,就感觉和没学差不多。学习就没什么动力了,如果我记下来,看博客越来越多,感觉这都是自己的知识,学习也就有了动力。
我希望小伙伴们,也都把自己学的东西记录下来,也不一定要写博客,但一定要归纳总结。
话不多说,看题:
题目:
给定一个字符串 s 和一些 长度相同 的单词 words 。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。
注意子串要与 words 中的单词完全匹配,中间不能有其他字符 ,但不需要考虑 words 中单词串联的顺序。
示例 1:
输入:s = "barfoothefoobarman", words = ["foo","bar"]
输出:[0,9]
解释:
从索引 0 和 9 开始的子串分别是 "barfoo" 和 "foobar" 。
输出的顺序不重要, [9,0] 也是有效答案。
我解这道题,的思路,是双指针,这类题,我觉的用双指针非常好做
思路:
1,首先我们用map1集合存储words里面的字符串,key是字符串,values是该字符串的个数,因为words里面的单词,可能是重复的,再用一个map2集合存储,遍历的字符串,这样两个集合做对比就能判断遍历的字符串是否符合。
2,首先我们将start指针,指向b,下标为0,题目说words中的字符串相同,都为“L”长度,我们将从下标0开始,移动L个长度,end就指向了f下标为3,截取下标start到end的字符,判断map集合是否包含,并且map2集合里的个数并且加上这个是否大于map集合的个数,如果满足,将字符串加入map2,。
3,继续将end向后移L长度,直到连续截取的子串个数,等于words单词的个数,满足条件。将初始下标加入集合中去。
4,将start指针后移,重复上述过程。
4,将map1指针后移,重复上面的过程直到,start指针指向的下标,到字符串末尾,大于words里单词的总长度,再往下移动,就截取不到满足条件的字符串的个数了。
代码:
代码一,是我的初版,代码,看着就很不舒服,所以我们再写完之后得优化,我们要精益求精,做一个优雅得码农,看如下代码,没有注释,就很难理解,而且if,else太多,不便于理解。
public static List<Integer> findSubstring(String s, String[] words) {
List<Integer> result = new LinkedList<>();
int length = s.length();
int wordChildLength = words[0].length();
int wordLength = words.length;
int totals = wordChildLength * wordLength;
if (totals > length) {
return result;
}
HashMap map = new HashMap();
for (String str : words) {
int count = (Integer) map.getOrDefault(str, 0);
map.put(str, count + 1);
}
int end = -1;
HashMap next = new HashMap();
for (int start = 0; start < length; start++) {
String str = "";
while (end + 1 < length) {
str += s.charAt(end + 1);
if (str.length() == wordChildLength) {
if (map.get(str) != null) {
int i = (Integer) map.get(str);
int j = (Integer) next.getOrDefault(str, 0);
if (j < i) {
next.put(str, j + 1);
} else {
break;
}
} else {
break;
}
str = "";
}
if (end + 1 - start + 1 == totals) {
result.add(start);
break;
}
++end;
}
end = start;
next.clear();
}
return result;
}
代码二,改良版本,着看着就很舒服么。
public static List<Integer> findSubstring1(String s, String[] words) {
List<Integer> result = new LinkedList<>();
int length = s.length();
//单词长度
int wordLength = words[0].length();
//words中单词的个数
int wordsCount = words.length;
//words里单词的总长度
int wordsTotal= wordLength * wordsCount;
if (wordsTotal > length) {
return result;
}
//将words中单词放入map1中
HashMap map1 = new HashMap();
for (String str : words) {
int count = (Integer) map1.getOrDefault(str, 0);
map1.put(str, count + 1);
}
//遍历字符串s
for (int start = 0; start <= length - wordsTotal; start++) {
HashMap map2 = new HashMap();
//用于计算,符合条件字符串的个数
int count=0;
while (true) {
//截取start指针到end指针的字符串,end=start+wordLength*count + wordLength
String str = s.substring(start+wordLength*count, start+wordLength*count + wordLength);
if (!map1.containsKey(str)) {
break;
}
int i = (Integer) map1.get(str);
int j = (Integer) map2.getOrDefault(str, 0);
if (j+1 > i) {
break;
}
map2.put(str, j + 1);
count++;
//将count等于words单词的个数,说明符合条条件,将初始下标加入结果集
if (count==wordsCount) {
result.add(start);
break;
}
}
}
return result;
}
如果对你有帮助,给个赞呗,谢谢