- 描述:给定一个字符串 s 和一些 长度相同 的单词 words 。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置(注意子串要与 words 中的单词完全匹配,中间不能有其他字符 ,但不需要考虑 words 中单词串联的顺序)
- 示例:输入:s = “barfoothefoobarman”, words = [“foo”,“bar”] -> 输出:[0,9],
输入:s = “barfoofoobarthefoobarman” , words = [“bar”,“foo”,“the”] -> 输出:[6,9,12] - 难度:困难
思路(滑动窗口 + 正则 + 排序)
- 给words排序,并得到目标子串,为了和后面s的子串进行匹配
- 由words中单词的单位长度,得到用于后续等分s子串的正则。
- 在遍历时,对截取的s子串用正则拆分、排序、合并成字符串,然后与目标子串进行比对,如果相同,则保存索引,否则遍历匹配下一个子串。
代码
var findSubstring = function(s, words) {
const tarChars = words.sort().join("");
const totalLen = tarChars.length;
const pieceLen = words[0].length;
const re = new RegExp(`[a-zA-Z]{${pieceLen}}`, 'g');
const res = [];
for (let i = 0, len = s.length - totalLen; i <= len; i++) {
if (!words.includes(s.substring(i, i + pieceLen))) continue;
const curChars = s.substring(i, i + totalLen).match(re).sort().join("");
if (curChars === tarChars) res.push(i);
}
return res;
};
优缺点
- 相较于其他方案,时间和空间复杂度较为均衡(均60%左右)
- 思路简单,代码更简洁
实测结果