LeetCode【0030】串联所有单词的子串

本文目录

  • 1 中文题目
  • 2 求解方法:滑动窗口
    • 2.1 方法思路
    • 2.2 Python代码
    • 2.3 复杂度分析
  • 3 题目总结

1 中文题目

给定一个字符串 s 和一个字符串数组 wordswords 中所有字符串 长度相同

s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。

例如,如果 words = [“ab”,“cd”,“ef”],
那么 “abcdef”, “abefcd”,“cdabef”, “cdefab”,“efabcd”, 和 “efcdab” 都是串联子串。
“acdbef” 不是串联子串,因为他不是任何 words 排列的连接。

返回所有串联子串在 s 中的开始索引。可以以 任意顺序 返回答案。

示例:

输入:s = "barfoothefoobarman", words = ["foo","bar"]
输出:[0,9]
解释:因为 words.length == 2 同时 words[i].length == 3,连接的子字符串的长度必须为 6。
子串 "barfoo" 开始位置是 0。它是 words 中以 ["bar","foo"] 顺序排列的连接。
子串 "foobar" 开始位置是 9。它是 words 中以 ["foo","bar"] 顺序排列的连接。
输出顺序无关紧要。返回 [9,0] 也是可以的。
输入:s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]
输出:[]
解释:因为 words.length == 4 并且 words[i].length == 4,所以串联子串的长度必须为 16。
s 中没有子串长度为 16 并且等于 words 的任何顺序排列的连接。
所以返回一个空数组。
输入:s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]
输出:[6,9,12]
解释:因为 words.length == 3 并且 words[i].length == 3,所以串联子串的长度必须为 9。
子串 "foobarthe" 开始位置是 6。它是 words 中以 ["foo","bar","the"] 顺序排列的连接。
子串 "barthefoo" 开始位置是 9。它是 words 中以 ["bar","the","foo"] 顺序排列的连接。
子串 "thefoobar" 开始位置是 12。它是 words 中以 ["the","foo","bar"] 顺序排列的连接。

提示:

  • 1 ≤ s . l e n g t h ≤ 1 0 4 1 \leq s.length \leq 10^4 1s.length104
  • 1 ≤ w o r d s . l e n g t h ≤ 5000 1 \leq words.length \leq 5000 1words.length5000
  • 1 ≤ w o r d s [ i ] . l e n g t h ≤ 30 1 \leq words[i].length \leq 30 1words[i].length30
  • words[i]s 由小写英文字母组成

2 求解方法:滑动窗口

2.1 方法思路

方法核心

使用滑动窗口和哈希表,按单词长度进行分组遍历,并动态维护当前窗口中的单词计数

实现步骤

(1)初始化:

  • 创建words中单词的频率字典
  • 计算关键参数(单词长度、单词数量等)

(2)滑动窗口:

  • 对每个可能的起始位置进行遍历
  • 维护当前窗口中的单词计数

(3)匹配过程:

  • 检查每个单词是否在目标词典中
  • 动态调整窗口大小
  • 记录有效的起始位置

方法示例

输入:s = "barfoothefoobarman", words = ["foo","bar"]

过程演示:
1. 初始化:
   word_len = 3
   word_count = 2
   word_dict = {"foo": 1, "bar": 1}

2. 第一轮遍历(i=0):
   检查: "bar" -> found
   检查: "foo" -> found, 添加索引0
   检查: "the" -> reset
   ...

3. 第二轮遍历(i=1)...

4. 第三轮遍历(i=2)...

返回:[0, 9]

2.2 Python代码

class Solution:
    def findSubstring(self, s: str, words: List[str]) -> List[int]:
        # 特殊情况处理
        if not s or not words:
            return []
            
        # 初始化结果列表
        result = []
        
        # 获取关键参数
        word_len = len(words[0])  # 每个单词的长度
        word_count = len(words)   # 单词的个数
        total_len = word_len * word_count  # 总长度
        s_len = len(s)  # 字符串长度
        
        # 如果字符串长度小于所需总长度,直接返回空列表
        if s_len < total_len:
            return []
            
        # 创建words中单词的计数字典
        word_dict = {}
        for word in words:
            word_dict[word] = word_dict.get(word, 0) + 1
            
        # 遍历所有可能的起始位置
        # 只需要遍历word_len个起始位置
        for i in range(word_len):
            # 初始化滑动窗口的左右边界
            left = i
            right = i
            
            # 当前窗口中的单词计数
            curr_dict = {}
            
            # 已匹配的单词数量
            count = 0
            
            # 右指针不超过字符串长度
            while right + word_len <= s_len:
                # 获取右侧单词
                word = s[right:right + word_len]
                right += word_len
                
                # 如果是目标单词
                if word in word_dict:
                    curr_dict[word] = curr_dict.get(word, 0) + 1
                    count += 1
                    
                    # 如果当前单词出现次数过多
                    while curr_dict[word] > word_dict[word]:
                        # 移除左侧单词直到符合要求
                        left_word = s[left:left + word_len]
                        curr_dict[left_word] -= 1
                        count -= 1
                        left += word_len
                        
                    # 如果找到所有单词
                    if count == word_count:
                        result.append(left)
                        # 移除最左侧的单词,继续寻找下一个匹配
                        left_word = s[left:left + word_len]
                        curr_dict[left_word] -= 1
                        count -= 1
                        left += word_len
                        
                else:
                    # 如果遇到非目标单词,重置窗口
                    left = right
                    curr_dict.clear()
                    count = 0
                    
        return result

2.3 复杂度分析

  • 时间复杂度:O(n * k),n是字符串长度,k是单个单词的长度
    • 实际上是O(n/k * k),因为每次移动k个字符
  • 空间复杂度:O(m)
    • m是words中不同单词的数量
    • 需要存储单词频率字典

3 题目总结

题目难度:困难
数据类型:字符串
数据结构:哈希表
应用算法:滑动窗口

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/915817.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Axure网络短剧APP端原型图,竖屏微剧视频模版40页

作品概况 页面数量&#xff1a;共 40 页 使用软件&#xff1a;Axure RP 9 及以上&#xff0c;非软件无源码 适用领域&#xff1a;短剧、微短剧、竖屏视频 作品特色 本作品为网络短剧APP的Axure原型设计图&#xff0c;定位属于免费短剧软件&#xff0c;类似红果短剧、河马剧场…

网安加·百家讲坛 | 仝辉:金融机构鸿蒙应用安全合规建设方案

作者简介&#xff1a;仝辉&#xff0c;北京娜迦信息科技发展有限公司攻防安全负责人&#xff0c;深耕移动应用安全领域十余年&#xff0c;获得过CISP、CISSP、OSCP、PMP、CCRC-CIASW等相关证书&#xff0c;参与多项移动应用安全标准起草&#xff0c;参与华为、平安集团、中国移…

C语言 strlen 函数 - C语言零基础入门教程

目录 一.strlen 函数简介二.strlen 函数实战三.猜你喜欢 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 语言基础入门 一.strlen 函数简介 在C 语言中&#xff0c;char 字符串也是一种非常重要的数据类型&#xff0c;我们可以使用 strlen 函数获取字符串长度&#xff1b;…

OceanStor Pacific系列 8.1.0 功能架构

功能架构 华为OceanStor Pacific系列提供基于三层的分布式存储架构&#xff0c;融合分布式文件、对象、大数据和块多个服务形态&#xff0c;支持文件、对象、大数据服务部署在一个集群&#xff0c;并统一管理。 华为OceanStor Pacific系列整体功能架构由存储接口层、存储服务…

Simulink中Matlab function使用全局变量

目录 一. 引言二. 普通Matlab function使用全局变量三. Simulink中的Matlab function使用全局变量四. 如何利用Matlab function的全局变量施加随机噪声 一. 引言 最近发现了之前仿真中的一个问题&#xff0c;记录一下备忘。 Matlab function中有时候需要用到全局变量&#xf…

react-markdown内容宽度溢出和换行不生效问题

情景复现&#xff1a; 解决办法&#xff0c;添加样式进行限制 /* index.css */ .markdown-container {word-break: break-word; /* 强制长单词断行 */white-space: pre-wrap; /* 保留空白符序列&#xff0c;但是正常地进行换行 */overflow-wrap: break-word; /* 在长单词或…

【C#设计模式(10)——装饰器模式(Decorator Pattern)】

前言 装饰器模式可以在运行时为对象添加额外的功&#xff0c;而无需修改原始对象的代码。这种方式比继承更加灵活。 代码 //蛋糕类&#xff08;抽象类&#xff09; public abstract class Cake {public abstract void Create(); } //奶油蛋糕类 public class CreamCake : Cak…

Diffusion Transformer模型结构解析(DiT、SD3、Flux)

Diffusion Transformer模型结构解析&#xff08;DiT、SD3、Flux&#xff09; 本文将通过 DiT、SD3、Flux 三个 DiT 相关工作&#xff0c;介绍 Diffusion 中的 Transformer 结构的应用与演进。注意 SD3 和 Flux 采用的 Flow Matching 的扩散模型形式化当然是很关键的改进&#…

给阿里云OSS绑定域名并启用SSL

为什么要这么做&#xff1f; 问题描述&#xff1a; 当用户通过 OSS 域名访问文件时&#xff0c;OSS 会在响应头中增加 Content-Disposition: attachment 和 x-oss-force-download: true&#xff0c;导致文件被强制下载而不是预览。这个问题特别影响在 2022/10/09 之后新开通 OS…

如何找到系统中bert-base-uncased默认安装位置

问题&#xff1a; 服务器中无法连接huggingface&#xff0c;故需要自己将模型文件上传 ubuntu 可以按照这个链接下载 Bert下载和使用&#xff08;以bert-base-uncased为例&#xff09; - 会自愈的哈士奇 - 博客园 里面提供了giehub里面的链接 GitHub - google-research/be…

【算法】区间DP

基本内容 [!NOte] 通过分治的思想实现DP数组 入门例子 NOI1995] 石子合并 - 洛谷 | 计算机科学教育新生态 题目要求&#xff1a;给定一圈石头数组&#xff0c;每个石头对应一个权重值&#xff0c;当两个石头合并时组成一个小石头堆&#xff0c;成本为两个石头权重值相加&#x…

机器学习—决定下一步做什么

现在已经看到了很多不同的学习算法&#xff0c;包括线性回归、逻辑回归甚至深度学习或神经网络。 关于如何构建机器学习系统的一些建议 假设你已经实现了正则化线性回归来预测房价&#xff0c;所以你有通常的学习算法的成本函数平方误差加上这个正则化项&#xff0c;但是如果…

第二十周机器学习笔记:初步认识PINN

第二十周周报 摘要Abstract一、初步认识物理信息神经网络&#xff08;PINN&#xff09;1.PINN的基本概念2. PINN与传统机器学习的区别3.构建PINN的步骤 二、代码实战——比较RNN、LSTM、Transformer在股市预测的表现1.RNN在股市预测中的表现2.LSTM在股市预测中的表现3.Transfor…

数据结构的时间复杂度和空间复杂度

目录 时间复杂度 空间复杂度 时间复杂度 基本操作的执行次数&#xff0c;为时间复杂度。 我们使用大O的渐进表示法来表示时间复杂度。 怎么使用&#xff1f; 先看例子&#xff1a; 在这个例子中&#xff0c; 基本操作为变量 count 的 加加 操作&#xff0c;并且&#xff0c;执行…

SQL面试题——奔驰SQL面试题 车辆在不同驾驶模式下的时间

SQL面试题——奔驰SQL面试题 我们的表大致如下 CREATE TABLE signal_log( vin STRING COMMENTvehicle frame id, signal_name STRING COMMENTfunction name, signal_value STRING COMMENT signal value , ts BIGINT COMMENTevent timestamp, dt STRING COMMENTformat yyyy-mm…

Mac 使用mac 原生工具将mp4视频文件提取其中的 mp3 音频文件

简介 Hello! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~ ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简介:因C语言结识编程,随后转入计算机专业,获得过国家奖学金,有幸在竞赛中拿过一些国奖、省奖…已保研 学习经验:扎实基础 + 多做笔…

多模态与大模型技术赋能企业数据资产平台建设

文章目录 一、政策背景分析二、企业数据资产运营平台架构思路三、统一多模技术赋能企业数据底座建设四、大模型助力数据资产管理降本增效五、典型案例分享 一、政策背景分析 2023年10月&#xff0c;国家数据局正式挂牌&#xff0c;负责协调推进数据基础制度建设&#xff0c;并…

【CentOS】中的Firewalld:全面介绍与实战应用(上)

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Linux &#xff1a;从菜鸟到飞鸟的逆袭》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、iptables 时代 2、firewalld 时代 3、 从 ipt…

使用 unicorn 和 capstone 库来模拟 ARM Thumb 指令的执行(一)

import binascii import unicorn import capstonedef printArm32Regs(mu):for i in range(66,78):print("R%d,value:%x"%(i-66,mu.reg_read(i)))def testhumb():CODE b\x1C\x00\x0A\x46\x1E\x00"""MOV R3, R0 的机器码&#xff1a;0x1C 0x00&#xf…

NVT新能德科技入职测评SHL题库更新:数字推理+演绎推理高分答案、真题解析

新能德的入职Verify测评主要考察应聘者的逻辑推理能力、数学能力、数据分析能力以及处理信息的能力。根据搜索结果&#xff0c;测评通常包含以下几个部分&#xff1a; 1. **语言理解**&#xff1a;这部分包括阅读理解、逻辑填空和语句排序。要求应聘者在17分钟内完成30题&#…