[优选算法专题二滑动窗口——串联所有单词的子串]
题目描述
题目解析
问题定义
在字符串 s
中寻找所有满足以下条件的子串起始索引:
- 子串由
words
数组中所有单词无重复、无遗漏地串联而成 - 子串中单词顺序可任意排列
核心解题策略:滑动窗口 + 哈希表
通过滑动窗口控制子串范围,用哈希表统计单词频次,实现高效匹配。
关键步骤解析
预处理阶段
- 构建基准哈希表:用
hash1
存储words
中每个单词的出现次数(作为匹配标准) - 计算关键参数:
word_len
:单个单词长度(题目保证所有单词长度相同)window_len
:目标子串总长度 =word_len × words.size()
- 构建基准哈希表:用
分组遍历策略
- 外层循环
for(int i=0; i<word_len; i++)
:- 因单词长度固定,目标子串的起始位置只能是
i, i+word_len, i+2×word_len...
- 分
word_len
组处理,覆盖所有可能的起始偏移,避免重复检查
- 因单词长度固定,目标子串的起始位置只能是
- 外层循环
滑动窗口匹配逻辑
- 窗口维护:用
left
和right
指针控制窗口范围,每次移动word_len
步 - 动态哈希表:
hash2
实时记录当前窗口内的单词频次 - 匹配计数器:
match
统计与hash1
频次一致的单词种类数
- 窗口维护:用
窗口调整规则
- 扩展窗口:右指针右移,将新单词加入
hash2
,若频次匹配则match++
- 收缩窗口:当窗口长度超过
window_len
时,左指针右移,移除左侧单词,若频次不匹配则match--
- 有效判断:当
match
等于hash1
中单词种类数时,记录left
为有效起始索引
- 扩展窗口:右指针右移,将新单词加入
完整代码实现:
复杂度分析
- 时间复杂度:O (L×N),其中 L 为
s
长度,N 为单词长度 - 空间复杂度:O (M),M 为
words
中单词的种类数(哈希表存储开销)