Leetcode:Substring with Concatenation of All Words
You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.
For example, given:
s: “barfoothefoobarman”
words: [“foo”, “bar”]
You should return the indices: [0,9].
(order does not matter).
题意
输入一个字符串s和一个字母等长的字符串数组words,在s中找到一个由words中所有单词组成的子串的起始位置,且words的单词只在子串中出现一次,并且中间也没有插入其他字符。
输入: s:”barfoothefoobarman”和words:[“foo”, “bar”]
s中符合条件的子串为barfoo和foobar,这两个子串的初始下标分别为0和9。
解题思路
题目中有一个很重要的点就是words中的单词都是等长的,针对这一点,从s串中截取一定长度的串,以map作为辅助检查这个子串是不是符合条件的串。按照这个思路写完代码后发现会超时,因为其中包含了太多的多余比较,例如示例中比较到第三个位置即foothe时,此时已知the已经不包含在words中,只要包含the的都一定不符合条件,希望直接能跳到第9的位置来比较foobar。
优化思路:
截取到子串后将其从后到前比较,如果检查到有不符合条件的单词,那么之前的单词也一定不符合条件,可以直接将前一个检查点作为截取字符串的开头:在检查到thefoo时,从后到前检比较,foo符合,the不符合,就直接从foo位置开始继续检查。
注意:
为了确保没有遗漏,还需要对字符串进行移位检查,移位范围为单词的长度。例如”aaa·aaa·b”和[“aa”,”aa”,”ab”],在检查完0-6子串后,还需要检查1-7子串,两次检查较小值作为下次截取字符串的开头。
代码在leetcode上提交后运行速度在前5%左右。
代码实现
1 | public class Solution { |