【刷题笔记】串联所有单词的子串||暴力通过||滑动窗口

串联所有单词的子串

1 题目描述

https://leetcode.cn/problems/substring-with-concatenation-of-all-words/

给定一个字符串 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”] 顺序排列的连接。

2 思路

这个题虽然是Hard,但是我感觉这也是一个靠暴力做的题,没有涉及到太多的技巧。

我的想法是,首先统计words中的每个字符串的数量:

在这里插入图片描述

然后以word.length * word[0].length大小的窗口对s进行遍历,统计每个窗口中分割出的元素数量。

在这里插入图片描述

如果符合,就添加进返回列表中。

3 详细设计

首先,我们对words里面的每个字符串进行编码:

Map<String, Integer> maps = new HashMap<>();
int pos = 0;
for (String str :
        words) {
    if (!maps.containsKey(str)) {
        maps.put(str, pos++);
    }
}

这样,我们就可以给予words中每个字符串一个唯一的编号,pos记录了一共有多少种word。

接下来我们统计每个word的出现次数:

int[] counts = new int[pos];
for (String str :
        words) {
    counts[maps.get(str)]++;
}

最后,我们设置窗口:

int end = total_len - 1; // 窗口的大小为total_len=word.length * word[0].length()
int start = 0;
while (end < s.length()) {
    int[] temp_table = new int[pos];
    for (int i = 0; i < words.length; i++) {
        // 对窗口内的单词进行分割遍历,
        // s.substring(start + i * single_word_len, start + (i + 1) * single_word_len)
        // 表示s的第(start+1)个窗口中的第(i+1)个单词
        String t = s.substring(start + i * single_word_len, start + (i + 1) * single_word_len);
        if (! maps.containsKey(t)) break; // 如果窗口中出现了不属于words中的字符串,跳出此次循环。
        temp_table[maps.get(t)]++; // 统计第(start+1)个窗口中的第(i+1)个单词的出现次数
    }
    boolean flag = true;
    for (int i = 0; i < pos; i++) {
        if (temp_table[i] != counts[i]) { // 判断相应单词的出现次数与words中是否一致
            flag = false; // 一旦有一个不一致的,设置标志位为false
            break;
        }
    }
    if (flag) reslist.add(start);
    start++;
    end++;
}

整体的时间复杂度应该是接近O(n*2*word.length)

4 代码

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        Map<String, Integer> maps = new HashMap<>();
        List<Integer> reslist = new ArrayList<>();

        int total_len = words.length * words[0].length();
        int single_word_len = words[0].length();

        int pos = 0;
        for (String str :
                words) {
            if (!maps.containsKey(str)) {
                maps.put(str, pos++);
            }
        }
        int[] counts = new int[pos];
        for (String str :
                words) {
            counts[maps.get(str)]++;
        }

        int end = total_len - 1;
        int start = 0;
        while (end < s.length()) {
            int[] temp_table = new int[pos];
            for (int i = 0; i < words.length; i++) {
                String t = s.substring(start + i * single_word_len, start + (i + 1) * single_word_len);
                if (! maps.containsKey(t)) break;
                temp_table[maps.get(t)]++;
            }
            boolean flag = true;
            for (int i = 0; i < pos; i++) {
                if (temp_table[i] != counts[i]) {
                    flag = false;
                    break;
                }
            }
            if (flag) reslist.add(start);
            start++;
            end++;
        }
        return reslist;
    }
}

在这里插入图片描述

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

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

相关文章

EasyMicrobiome-易扩增子、易宏基因组等分析流程依赖常用软件、脚本文件和数据库注释文件

啥也不说了&#xff0c;这个好用&#xff0c;给大家推荐&#xff1a;YongxinLiu/EasyMicrobiome (github.com) 大家先看看引用文献吧&#xff0c;很有用&#xff1a;https://doi.org/10.1002/imt2.83 还有这个&#xff0c;后面马上介绍&#xff1a;YongxinLiu/EasyAmplicon: E…

将项目放到gitee上

参考 将IDEA中的项目上传到Gitee仓库中_哔哩哔哩_bilibili 如果cmd运行ssh不行的话&#xff0c;要换成git bash 如果初始化后的命令用不了&#xff0c;直接用idea项放右键&#xff0c;用git工具操作

【Linux】进程控制--进程创建/进程终止/进程等待/进程程序替换/简易shell实现

文章目录 一、进程创建1.fork函数2.fork函数返回值3.写时拷贝4.fork常规用法5.fork调用失败的原因 二、进程终止1.进程退出码2.进程退出场景3.进程常见退出方法 三、进程等待1.为什么要进行进程等待2.如何进行进程等待1.wait方法2.waitpid方法3.获取子进程status4.进程的阻塞等…

【双向链表的实现】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 1. 双向链表的结构 2. 双向链表的实现 2.1 头文件 ——双向链表的创建及功能函数的定义 2.2 源文件 ——双向链表的功能函数的实现 2.3 源文件 ——双向链表功能的…

计算机网络:应用层(下篇)

文章目录 前言一 、电子邮件&#xff08;Email&#xff09;1.邮件服务器2.SMTP[RFC 2821]3.邮件报文格式4.邮件访问协议 二、DNS&#xff08;域名系统&#xff09;1.DNS的历史2.DNS总体思路和目标&#xff08;1&#xff09;问题1&#xff1a;DNS名字空间&#xff08;2&#xff…

(项目已开源)社区求助 哪位大佬能不能帮我 将box1 audio 和 box2 slider滑块 和 box3 歌词滚动区域 进行联动

(项目已开源)社区求助 哪位大佬能不能帮我 将box1 audio 和 box2 slider滑块 和 box3 歌词滚动区域 进行联动 链接&#xff1a;https://pan.baidu.com/s/16lpEW6L5jrHfhsG7EXocLw?pwdkryy 提取码&#xff1a;kryy <!--社区求助 哪位大佬能不能帮我 将box1 audio 和 box2 s…

rest_framework_django 学习笔记二(视图路由)

rest_framework_django 学习笔记二&#xff08;视图路由&#xff09; rest_framwork_django学习笔记一(序列化器) 一、rest framework 中Request 与 Response 1、Request REST framework 传入视图的request对象不再是Django默认的HttpRequest对象&#xff0c;二是REST Fame…

Git常用命令#切换分支

要在 Git 中切换分支&#xff0c;你可以使用 git checkout 命令。 a.创建新分支并切换到该分支 如果你想要创建一个新分支并立即切换到该分支&#xff0c;可以使用以下命令&#xff1a; git checkout -b 新分支名这会创建一个名为 新分支名 的新分支&#xff0c;并将你的工作目…

OSEK OS任务调度的底层逻辑

先参考 FreeRTOS的任务触发底层逻辑 简述RTOS任务调度底层逻辑 AUTOSAR-OS的调度机制-调度表&#xff08;没理解透&#xff0c;继续更新&#xff09; OSEK与FreeRTOS在任务调度上最大的区别在于&#xff0c;FreeRTOS是基于全抢占任务调度和时间片轮转调度机制&#xff0c;具有…

(一)C语言概述

文章目录 一、C语言1、计算机结构组成 二、第一个C语言程序&#xff1a;hello world1、编写C语言代码&#xff1a;hello.c2、通过gcc编译C代码&#xff08;1&#xff09;gcc编译器介绍&#xff08;2&#xff09;Window平台中gcc环境配置 3、代码分析&#xff08;1&#xff09;#…

css新闻链接案例

利用html和css构建出新闻链接案例&#xff0c;使用渐变色做出背景色变化 background: linear-gradient(to bottom, rgb(137, 210, 251), rgb(238, 248, 254), white); 利用背景图片&#xff0c;调整位置完成 dd { height: 28px; line-height: 28px; background-image: url(./图…

10.30 作业 C++

设计一个Per类&#xff0c;类中包含私有成员:姓名、年龄、指针成员身高、体重&#xff0c;再设计一个Stu类&#xff0c;类中包含私有成员:成绩、Per类对象p1&#xff0c;设计这两个类的构造函数、析构函数和拷贝构造函数。 #include <iostream>using namespace std;clas…

Discuz论坛自动采集发布软件

随着网络时代的不断发展&#xff0c;Discuz论坛作为一个具有广泛用户基础的开源论坛系统&#xff0c;其采集全网文章的技术也日益受到关注。在这篇文章中&#xff0c;我们将专心分享通过输入关键词实现Discuz论坛的全网文章采集&#xff0c;同时探讨采集过程中伪原创的发布方法…

springboot+jsp+java房屋销售出租赁网站的ssm设计与实现7xcvq

三、研究方案&#xff08;主要研究内容、目标、研究方法等&#xff09; 主要研究内容 房屋租售网站采用的开发框架为springboot框架&#xff0c;也就是Spring mvc、Spring、MyBatis这三个框架&#xff0c;页面设计用的是jsp技术作为动态页面文件设计&#xff0c;jsp文件里可以对…

Glove学习笔记

global vectors for word representation B站学习视频 1、LSA与word2vec 我们用我们的见解&#xff0c;构建一个新的模型&#xff0c;Glove&#xff0c;全局向量的词表示&#xff0c;因为这个模型捕捉到全局预料的统计信息。 LSA:全局矩阵分解word2vec&#xff1a;局部上下文…

第一百八十五回 如何禁止页面跟随手机自动旋转

文章目录 1. 概念介绍2. 使用方法2.1 全面禁止2.2 局部禁止3. 示例代码4. 内容总结我们在上一章回中介绍了"如何自定义Radio组件"相关的内容,本章回中将介绍 如何禁止页面随手机自动旋转.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 在手机默认设置下,手机…

系统渗透-lin20230502(解析+环境)

B-5&#xff1a;系统渗透&#xff1a; 仅能获取lin20230502的IP地址 1.在渗透机中对服务器主机进行信息收集&#xff0c;将服务器开启的端口号作为Flag值提交&#xff1b; 2.在渗透机中对服务器主机进行渗透&#xff0c;在服务器主机中获取服务器主机名称&#xff0c;将主机名作…

Python实验项目8 :科学计算与可视化

1&#xff1a;创建 numpy 数组。 要求&#xff1a; &#xff08;1&#xff09;使用 array()函数、empty()函数、zeros()函数、linspace()函数等创建 numpy 数组。 &#xff08;2&#xff09;使用 numpy 数组的索引和切片方法访问数组元素。 # 要求&#xff1a; # &#xff0…

SSM校园组团平台系统开发mysql数据库web结构java编程计算机网页源码eclipse项目

一、源码特点 SSM 校园组团平台系统是一套完善的信息系统&#xff0c;结合springMVC框架完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模…

pycharm 创建vue并实现简易路由功能

使用pycharm创建vue项目时&#xff0c;选择vite来创建vue。为什么使用vite&#xff1f;因为vite是专门针对vue开发的打包框架&#xff0c;以前使用vue-cli来创建vue项目&#xff0c;就是使用的webpack来进行打包的&#xff0c;现在有了vite&#xff0c;就尽量使用vite来创建vue…