力扣题解30. 串联所有单词的子串

Python&Java双语解决力扣必刷算法,题号30. 串联所有单词的子串

目录

题目描述

解题思路

完整代码

Python

Java


题目描述

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

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

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

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

示例 1:

输入: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] 也是可以的。

示例 2:

输入:s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]
输出:[]
解释:因为 words.length == 4 并且 words[i].length == 4,所以串联子串的长度必须为 16。
s 中没有子串长度为 16 并且等于 words 的任何顺序排列的连接。
所以我们返回一个空数组。

示例 3:

输入: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.length <= 104
  • 1 <= words.length <= 5000
  • 1 <= words[i].length <= 30
  • words[i] 和 s 由小写英文字母组成

解题思路

        要解决这个问题,我们可以使用一个滑动窗口的方法。核心思路是维护一个窗口,这个窗口的大小是所有 words 中字符串长度总和。我们逐个移动这个窗口,然后检查窗口内的子串是否是 words 中所有字符串的某种排列。

具体步骤如下:

  1. 首先,计算 words 中所有字符串的总长度,这将是我们滑动窗口的大小。
  2. 使用一个哈希表 wordCount 来统计 words 数组中每个单词出现的次数。
  3. 遍历字符串 s,对于每个可能的窗口起始位置,使用另一个哈希表 seen 来记录当前窗口中出现的单词及其频率。
  4. 检查当前窗口内的单词是否与 words 中的单词完全匹配(即 seenwordCount 相等),如果匹配,则将当前窗口的起始索引添加到结果列表中。
  5. 最后,返回结果列表。

完整代码

Python

class Solution:
    def findSubstring(self, s: str, words: List[str]) -> List[int]:
        if not words or not s:
            return []

        word_len = len(words[0])
        total_len = word_len * len(words)
        word_count = {}
        result = []

        # 统计 words 中每个单词出现的次数
        for word in words:
            if word in word_count:
                word_count[word] += 1
            else:
                word_count[word] = 1

        # 遍历每个可能的窗口起始位置
        for i in range(word_len):
            left = i
            right = i
            seen = {}

            while right + word_len <= len(s):
                word = s[right:right + word_len]
                right += word_len

                if word in word_count:
                    if word in seen:
                        seen[word] += 1
                    else:
                        seen[word] = 1

                    # 如果当前单词的出现次数超过了它在 words 中的次数,移动左指针
                    while seen[word] > word_count[word]:
                        seen[s[left:left + word_len]] -= 1
                        left += word_len

                    # 如果窗口大小等于总长度,记录起始位置
                    if right - left == total_len:
                        result.append(left)
                else:
                    # 当前单词不在 words 中,重置 seen,移动左指针到 right
                    seen.clear()
                    left = right

        return result

        这段代码定义了一个 Solution 类,该类包含一个 findSubstring 方法。这个方法接受一个字符串 s 和一个字符串列表 words 作为输入,返回一个整数列表,表示所有符合条件的起始索引。代码的逻辑与之前讨论的相同,首先计算必要的变量,如每个单词的长度、总长度和单词计数哈希表。然后,遍历字符串 s 的每个可能的窗口起始位置,使用另一个哈希表 seen 来跟踪当前窗口中的单词及其出现次数,并最终确定符合条件的起始索引。

通过

Java

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        List<Integer> result = new ArrayList<>();
        if (words == null || words.length == 0 || s == null || s.length() == 0) {
            return result;
        }

        int wordLen = words[0].length();
        int totalLen = wordLen * words.length;
        Map<String, Integer> wordCount = new HashMap<>();

        // 统计words中每个单词出现的次数
        for (String word : words) {
            wordCount.put(word, wordCount.getOrDefault(word, 0) + 1);
        }

        // 遍历每个可能的窗口起始位置
        for (int i = 0; i < wordLen; i++) {
            int left = i, right = i;
            Map<String, Integer> seen = new HashMap<>();

            while (right + wordLen <= s.length()) {
                String word = s.substring(right, right + wordLen);
                right += wordLen;

                if (wordCount.containsKey(word)) {
                    seen.put(word, seen.getOrDefault(word, 0) + 1);

                    // 如果当前单词的出现次数超过了它在words中的次数,移动左指针
                    while (seen.get(word) > wordCount.get(word)) {
                        String leftWord = s.substring(left, left + wordLen);
                        seen.put(leftWord, seen.get(leftWord) - 1);
                        left += wordLen;
                    }

                    // 如果窗口大小等于总长度,记录起始位置
                    if (right - left == totalLen) {
                        result.add(left);
                    }
                } else {
                    // 当前单词不在words中,重置seen,移动左指针到right
                    seen.clear();
                    left = right;
                }
            }
        }

        return result;
    }
}

        这个Java实现遵循了之前讨论的逻辑,使用了HashMap来存储单词的计数,以及一个ArrayList来存储结果。遍历字符串s的每个可能的起始位置,逐个检查窗口内的子串是否满足条件,最终返回所有符合条件的起始索引。在Java中处理字符串和集合的方式与Python有所不同,比如使用substring方法来获取子字符串,以及使用MapgetOrDefault方法来简化计数逻辑。

通过

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

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

相关文章

Milvus的相似度指标

官网&#xff1a;https://milvus.io/docs/metric.md版本: v2.3.x 在 Milvus 中&#xff0c;相似度度量用于衡量向量之间的相似度。选择良好的距离度量有助于显着提高分类和聚类性能。下表展示了这些广泛使用的相似性指标如何与各种输入数据形式和 Milvus 索引相匹配。 一、浮…

数据结构---复杂度(2)

1.斐波那契数列的时间复杂度问题 每一行分别是2^0---2^1---2^2-----2^3-------------------------------------------2^(n-2) 利用错位相减法&#xff0c;可以得到结果是&#xff0c;2^(n-1)-1,其实还是要减去右下角的灰色部分&#xff0c;我们可以拿简单的数字进行举例子&…

力扣题目训练(18)

2024年2月11日力扣题目训练 2024年2月11日力扣题目训练561. 数组拆分566. 重塑矩阵572. 另一棵树的子树264. 丑数 II274. H 指数127. 单词接龙 2024年2月11日力扣题目训练 2024年2月11日第十八天编程训练&#xff0c;今天主要是进行一些题训练&#xff0c;包括简单题3道、中等…

第十五届蓝桥杯-UART接收不定长指令的处理

学习初衷&#xff1a; 不仅仅为了比赛&#xff01; 目录 一、问题引入 二、UART常用的三种工作模式 1.UART工作在中断模式 2.UART工作在DMA模式下 3.uart工作在接收转空闲的模式下 三、获取指令中需要的数据 四、printf函数的实现 一、问题引入 问题引入&#xff1a;请…

定制红酒:如何根据客户需求调整红酒口感与风格

在云仓酒庄洒派&#xff0c;云仓酒庄洒派深知不同消费者对于红酒的口感与风格有着不同的喜好和需求。因此&#xff0c;云仓酒庄洒派根据消费者的具体要求&#xff0c;灵活调整红酒的口感与风格&#xff0c;以满足他们的期望。 首先&#xff0c;云仓酒庄洒派会与消费者进行深入的…

【axios】你的进度条准确吗

1、axios监听进度 上传和下载操作在前端中是非常常见的&#xff0c;当我们想知道上传或下载的进度时也不难&#xff0c;axios已经实现了监听进度的方法 import axios from axios// 上传请求 axios.post(/api/v1/upload, {data: xxx},{// onUploadProgress回调可以获取进度onU…

SSM整合项目(删除家居 + 分页查询)

1.删除家居 1.需求分析 2.编写Service层 1.FurnService.java 添加方法 //删除家居public void del(Integer id);2.FurnServiceImpl.java 实现方法 Overridepublic void del(Integer id) {furnMapper.deleteByPrimaryKey(id);}3.单元测试 Testpublic void del() {furnService.…

JavaScript基础6之执行上下文、作用域链、函数创建、函数激活、checkScope的执行过程、闭包、this

JavaScript基础 执行上下文执行上下文中的属性变量对象全局上下文的变量对象函数上下文执行过程进入执行上下文代码执行思考题 作用域链函数创建函数激活checkScope的执行过程总结 闭包分析闭包 this 执行上下文 执行上下文中的属性 每一个执行上下文都有三个核心属性 变量对…

haproxy-高性能负载均衡反向代理服务

目录 一、HAProxy&#xff08;High Availability Proxy&#xff09;概述 1、HAProxy的概念 2、HAProxy的主要特性 3、HAProxy的优缺点 4、Haproxy负载均衡策略 5、LVS、nginx、HAProxy的区别 二、安装HAProxy 1、yum安装 2、第三方rpm包安装 3、编译安装 3.1 解决 l…

【AI视频教程】只需5步,AI作出鸡你太美视频

1.视频效果 2.准备工作 制作视频效果&#xff0c;需要准备下面3个条件&#xff1a; 准备stable diffusion的环境剪辑一段【鸡你太美】原版视频stable diffusion安装sd-webui-IS-NET-pro插件 2.1部署stable diffusion环境 这里还是建议大家用云平台部署stable diffusion&am…

一个测开人员的大厂面试总结

前言 其实我已经入职有好一段时间了&#xff0c; 这里决定总结一下一些面试经验。 我呢&#xff0c;最终还是决定要离开服务了 5 年多的公司。 而这次跳槽历经 3 个月&#xff0c;前后聊了 10 家公司&#xff0c;进行了将近 40 场面试, 基本都是 41 的流程 (技术面 HR 面)&…

计算机网络-第5章 运输层(2)

5.6 TCP可靠传输实现 以字节为单位的滑动窗口。 发送窗口已满&#xff0c;停止发送。 发送和接收的数据都来自缓存。 超时重传时间RTO选择&#xff1a;自适应算法&#xff0c; 选择确认SACK&#xff1a;只传送缺少的数据。大多数实现还是重传所有未被确认的数据块。 5.7 TCP的…

小程序学习 1

pages/goods/search/home.wxml首页功能设定 1. loading入场 2. 下拉刷新 3. 搜索栏 4. 分类切换 5. 商品列表 6. 规格弹层 7. 加载更多 <view style"text-align: center; color: #b9b9b9" wx:if"{{pageLoading}}"><t-loading theme"circula…

网络安全防御保护 Day7

1.因为FW1和FW2已处于双机热备状态&#xff0c;所以只需要对主设备进行配置即可。进入FW1的配置界面&#xff0c;选择“网络”界面&#xff0c;点击“IPsec”&#xff0c;进行IPsec通道的基本配置&#xff0c;这里选择的是“电信”链路。 2.完成上述配置后&#xff0c;进行待加…

面试官:线程调用2次start会怎样?我支支吾吾没答上来

写在开头 在写完上一篇文章《Java面试必考题之线程的生命周期&#xff0c;结合源码&#xff0c;透彻讲解!》后&#xff0c;本以为这个小知识点就总结完了。 但刚刚吃晚饭时&#xff0c;突然想到了多年前自己面试时的亲身经历&#xff0c;决定再回来补充一个小知识点&#xff…

【DPDK】基于dpdk实现用户态UDP网络协议栈

文章目录 一.背景及导言二.协议栈架构设计1. 数据包接收和发送引擎2. 协议解析3. 数据包处理逻辑 三.网络函数编写1.socket2.bind3.recvfrom4.sendto5.close 四.总结 一.背景及导言 在当今数字化的世界中&#xff0c;网络通信的高性能和低延迟对于许多应用至关重要。而用户态网…

并发通信(网络进程线程)

如果为每个客户端创建一个进程&#xff08;或线程&#xff09;&#xff0c;因为linux系统文件标识符最多1024位&#xff0c;是有限的。 所以使用IO复用技术&#xff0c;提高并发程度。 阻塞与非阻塞 阻塞式复用 非阻塞复用 信号驱动IO 在属主进程&#xff08;线程中声明&…

4、Generator、class类、继承、Set、Map、Promise

一、生成器函数Generator 1、声明generator函数 function* 函数名() { }调用生成器函数 需要next()返回一个generator对象&#xff0c;对象的原型上有一个next(),调用返回对象{value:yield后面的值,done} function* fn() {console.log("我是生成器函数") } let it…

JAVA开发常见小问题整合

文章目录 1&#xff1a;身份证工具类相关方法1.1 身份证脱敏处理 2&#xff1a;字符串补零处理(此处是JAVA类的方法&#xff0c;并无引用StrUtil)3&#xff1a;springboot前后端分离&#xff0c;后端返回json字符串带斜杠问题处理4&#xff1a;WebUploader 文件上传组件 -编辑回…

java基本认识?java跨平台原理?jdk、jre、jvm的联系?

1、java基本认识 1.1 java语言 语言&#xff1a;人与人交流沟通的方式。比如&#xff0c;你好、hello等。 计算机语言&#xff1a;人与计算机之间进行信息交流的一种特殊方式。比如&#xff0c;Java语言、C语言、C等。 1.2 java的来源 Java 是由 Sun Microsystems 公司于 …