当前位置: 首页 > news >正文

串联所有单词的子串

题目链接

串联所有单词的子串

题目描述


注意点

  • words[i] 和 s 由小写英文字母组成
  • 1 <= words.length <= 5000
  • 可以以 任意顺序 返回答案
  • words中所有字符串长度相同

解答思路

  • 根据滑动窗口+哈希表解决本题,哈希表存储words中所有的单词及单词的出现次数,滑动窗口时使用另一个哈希表存储当前窗口内已经出现的单词及单词的出现次数
  • 因为words中所有字符串长度相同,所以在移动滑动窗口右边界时应该以单词为维度,每次移动wordLen个单位,然后判断该部分单词rightWord是否能作为串联串联所有单词的子串的一部分,有以下三种情况:
    • 如果rightWord根本不属于words中的单词,说明包含该单词时的子串一定不满足题意,此时需要将滑动窗口直接移动到该单词右侧,也就是直接重置滑动窗口的左右边界
    • 如果rightWord属于words中的单词,但是当前滑动窗口中该单词数量已经达到words中该单词的最大数量,此时需要移动滑动窗口的左边界,移动时每次也同样移动wordLen个单位,直到左侧找到一个与rightWord相同的值leftWord(一定能找到),将滑动窗口左边界移动到leftWord右侧
    • 如果rightWord属于words中的单词,且当前滑动窗口中该单词数量还未超过words中该单词的最大数量,此时满足题意,继续移动滑动窗口右边界(注意判断该滑动窗口已经是串联所有单词的子串的情况)
  • 上述过程并未判断所有情况,因为每次移动边界时都是以wordLen为单位,如果从字符串首位置开始,可能会忽略1,2…(wordLen - 1)为起始位置的情况,观察规律可得,只需要对1,2…(wordLen - 1)为起始位置都执行一次上述的操作就可以考虑到所有的情况

代码

class Solution {public List<Integer> findSubstring(String s, String[] words) {List<Integer> res = new ArrayList<>();int wordSum = words.length;int wordLen = words[0].length();if (s.length() < wordSum * wordLen) {return res;}Map<String, Integer> map = new HashMap<>();for (String word : words) {map.put(word, map.getOrDefault(word, 0) + 1);}for (int i = 0; i < wordLen; i++) {int left = i;int right = i;int currWordSum = 0;Map<String, Integer> visitedMap = new HashMap<>();while (right + wordLen <= s.length()) {// 长度越界,剩下的子串一定无法串联所有单词if (left + (wordSum - currWordSum) * wordLen > s.length()) {break;}String leftWord = s.substring(left, left + wordLen);String rightWord = s.substring(right, right + wordLen);// 该单词不存在,则有该单词的部分都一定不满足题意,将滑动窗口左边界移动至该单词右侧if (map.get(rightWord) == null) {left = right + wordLen;visitedMap = new HashMap<>();currWordSum = 0;}// 该单词存在但words中已经没有该单词if (map.get(rightWord) != null && visitedMap.getOrDefault(rightWord, 0) >= map.get(rightWord)) {while (left < right && !rightWord.equals(leftWord)) {visitedMap.put(leftWord, visitedMap.get(leftWord) - 1);left += wordLen;leftWord = s.substring(left, left + wordLen);currWordSum--;}left += wordLen;}// 该单词存在满足题意if (map.get(rightWord) != null && visitedMap.getOrDefault(rightWord, 0) < map.get(rightWord)) {visitedMap.put(rightWord, visitedMap.getOrDefault(rightWord, 0) + 1);currWordSum++;// 已找到串联所有单词的子串if (currWordSum == wordSum) {res.add(left);visitedMap.put(leftWord, visitedMap.get(leftWord) - 1);currWordSum--;left += wordLen;}}right += wordLen;}}return res;}
}

关键点

  • 滑动窗口的思想
  • 移动滑动窗口时其对应的哈希表的变化
  • 移动滑动窗口右边界时对应单词是否是串联所有单词的子串的三种情况
http://www.lryc.cn/news/311595.html

相关文章:

  • 【会议征稿通知】第四届经济发展与商业文化国际学术会议(ICEDBC2024)
  • 回溯算法套路③排列型回溯+N皇后【基础算法精讲 16】
  • MyBatis-Plus 框架中的自定义元对象处理器
  • Node.js_基础知识(fs模块 - 文件操作)
  • 基于C#开发OPC DA客户端——搭建KEPServerEX服务
  • 让你的函数,返回你需要的“两个值” (函数传址、结构体作为参数传参)
  • 快速上手:在 Android 设备上运行 Pipy
  • 【操作系统学习笔记】文件管理1.3
  • 基于springboot+vue的酒店管理系统
  • Linux 相关命令
  • 阿里云搭建私有docker仓库(学习)
  • MySQL数据库基本操作(一)
  • 【暗月安全】2021年渗透测试全套培训视频
  • HTML极速入门
  • Django框架——请求与响应
  • rearrangement-challenge-2022环境使用学习(一)
  • [Uniapp]携带参数跳转界面(两种方法)
  • Scrapy与分布式开发(2.1.2):python常用网络请求库httpx
  • 07. Nginx进阶-Nginx负载均衡
  • windows/linux下其他位置调用指定nodejs脚本报错Error: Cannot find module ‘esm’
  • 2024-03-05 linux 分区老显示满,Use 100%,原因是SquashFS 是一种只读文件系统,它在创建时就已经被填满,所有空间都被使用。
  • 蓝桥杯倒计时 41天 - KMP 算法
  • 《汇编语言》- 读书笔记 - 第13章-int 指令
  • 深入了解 Golang 条件语句:if、else、else if 和嵌套 if 的实用示例
  • 大数据和机器学习在气象预报中的应用-张平文院士
  • C#高级:Winform桌面开发中DataGridView的详解
  • java八股文复习-----2024/03/05----基础---反射,动态代理。序列化
  • 【人工智能】Anthropic发布强大的Claude3对齐GPT-4,大模型杂谈个人感想
  • 基于openKylin与RISC-V的MindSpore AI项目实践
  • 【牛客】VL64 时钟切换