Leetcode30-串联所有单词的子串[三种方法]

news2024/12/26 11:52:58

文章目录

  • 30. 串联所有单词的子串(hard)
    • 方法一:暴力
    • 方法二:滑窗
    • 再次优化
  • 小记-map的使用

30. 串联所有单词的子串(hard)

在这里插入图片描述

方法一:暴力

思路:
map存每个单词出现的个数。枚举s串的每一个下标i作为起始点:从起始点i开始,每m位(m = words[i].length)截出一个子串,一共截出n个(n = words.length),在map中查询该子串是否为单词且还有剩余个数——若否,则i不是答案;若是,剩余个数减1。如果n个单词都通过了检查,则i是答案。每一趟i的循环都要将map复原。

数据范围:
1 <= s.length <= 104
1 <= words.length <= 5000
1 <= words[i].length <= 30

时间复杂度分析:
O ( 10000 ∗ ( 5000 ∗ 30 ∗ l o g 5000 + 5000 ) ) O(10000*(5000*30*log5000+5000) ) O(10000(500030log5000+5000))

所以很自然的超时了(通过175/179)
在这里插入图片描述
附上代码:

struct p {
    int total, res;
};
class Solution {
    vector<int> ans;
    map<string, p> mymap;
    int n; //字符串s长度
    int cnt; //单词个数
    int m; //每个单词的长度
public:
    vector<int> findSubstring(string s, vector<string>& words) 
    {
        cnt = words.size();
        n = s.length();
        m = words[0].length();
        for (auto & word : words)
            mymap[word].total++;

        for (int i=0; i<n; i++)
        {
            for (auto &[k,v] : mymap)
                v.res = v.total;

            int j;
            for (j = i; j<i+cnt*m; j+=m )
            {
                string tmpword = s.substr(j, m);
                if (mymap[tmpword].res > 0)
                    mymap[tmpword].res--;
                else
                    break;
            }
            if (j == i+cnt * m)
                ans.push_back(i);
            
        }
        return ans;
    }
};

方法二:滑窗

思路:
单词分割方式只有m种(m = words[i].length)。比如s="acbdefghijkl"且m=3的话:

abc def ghi jkl
bcd efg hij
cde fgh ijk
def ghi jkl(到这儿就会发现和第一行重复了)

所以无需像方法一那样枚举每一个s串的下标,而是只枚举前m个下标。
然后对于每一种分割方式。
map1存单词表中每个单词出现的个数。map2存每个单词到整数的映射。数组cnt[5000]存滑窗中每个单词出现的次数。

通过代码:

class Solution {
    vector<int> ans;
    map<string, int> map1, map2; //map1存单词表中每个单词出现的个数。map2存每个单词到整数的映射。
    int st[5000];
public:
    vector<int> findSubstring(string s, vector<string>& words) 
    {
        int cnt = words.size(), n = s.length(), m = words[0].length(), num = 0;
        for (auto & word : words)
            map1[word]++;
        for (auto &[k,v] : map1)
            map2[k] = num++;
        s = s +  "          " + "          " + "          ";
        for (int i=0; i<m; i++)
        {
            int pl = i, pr = i;
            while (pr <= n)
            {
                string currWord = s.substr(pr, m);
                int currWordIndex = map2[currWord];
                int currWordCnt = map1[currWord];
                if (st[currWordIndex] >= currWordCnt)
                {
                    // 检查是否为答案
                    if (pr - pl == m * cnt) ans.push_back(pl);
                    //pl右移
                    while (st[currWordIndex] >= currWordCnt)
                    {
                        st[map2[s.substr(pl, m)]]--;
                        pl += m;
                    }
                }
                st[currWordIndex]++;
                pr+=m;
            }
        }
        return ans;
    }
};

在这里插入图片描述

再次优化

这个思路已经很好了,但是为什么运行还是太慢?因为map中存了大量不属于单词表的串。

考虑下面的代码,size是1不是0

map<string, int> mm;
cout << mm["haha"];
printf("%d", mm.size());

所以为了避免不属于单词表的子串存入map1和map2,代码改为如下:

class Solution {
    vector<int> ans;
    map<string, int> map1, map2; //map1存单词表中每个单词出现的个数。map2存每个单词到整数的映射。
    int st[5000];
public:
    vector<int> findSubstring(string s, vector<string>& words) 
    {
        int cnt = words.size(), n = s.length(), m = words[0].length(), num = 0;
        for (auto & word : words)
            map1[word]++;

        for (auto &[k,v] : map1)
            map2[k] = num++;

        for (int i=0; i<m; i++)
            s += " ";

        for (int i=0; i<m; i++)
        {
            int pl = i, pr = i;

            while (pr <= n)
            {
                string currWord = s.substr(pr, m);
                if (map1.count(currWord) == 0)
                {
                    if (pr - pl == m * cnt) ans.push_back(pl);
                    while (pl < pr)
                    {
                        st[map2[s.substr(pl, m)]]--;
                        pl += m;
                    }
                    pr += m;
                    pl = pr;
                    continue;
                }

                int currWordIndex = map2[currWord];
                int currWordCnt = map1[currWord];
                if (st[currWordIndex] >= currWordCnt)
                {
                    // 检查是否为答案
                    if (pr - pl == m * cnt) ans.push_back(pl);
                    //pl右移
                    while (st[currWordIndex] >= currWordCnt)
                    {
                        st[map2[s.substr(pl, m)]]--;
                        pl += m;
                    }
                }
                st[currWordIndex]++;
                pr+=m;
            }
        }
        return ans;
    }
};

在这里插入图片描述
这个结果就很好了。

小记-map的使用

  1. 考虑下面的代码,size是1不是0
map<string, int> mm;
cout << mm["haha"];
printf("%d", mm.size());
  1. map的遍历方法
for (auto &[k,v] : map1)
	map2[k] = num++;

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

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…

深度学习模型部署(六)TensorRT工作流and入门demo

TensorRT工作流程 官方给出的步骤&#xff1a; 总结下来可以分为两大部分&#xff1a; 模型生成&#xff1a;将onnx经过一系列优化&#xff0c;生成tensorrt的engine模型 选择batchsize&#xff0c;选择精度precision&#xff0c;模型转换 模型推理&#xff1a;使用python或…

软考 系统架构设计师之回归及知识点回顾(6)

接前一篇文章&#xff1a;软考 系统架构设计师之回归及知识点回顾&#xff08;5&#xff09; 10. 边缘计算 边云协同 边缘计算与云计算各有所长&#xff0c;云计算擅长全局性、非实时、长周期的大数据处理与分析&#xff0c;能够在长周期维护、业务决策支撑等领域发挥优势&…

微信小程序问题定位——sourcemap文件

使用sourceMap在微信小程序中进行线上问题定位&#xff0c;主要可以通过以下步骤实现&#xff1a; 下载微信开发者工具首先&#xff0c;确保已经安装了微信开发者工具&#xff0c;这是进行小程序开发和调试的基础。登录微信公众平台并下载sourceMap文件&#xff1a;登录微信小…

Mysql中的MVCC

”真正学会&#xff0c;如你般自由~“ MVCC机制简介 MVCC(Multi-Version-Concurrency-Control)多版本并发控制&#xff0c;MVCC 是一种并发控制的方法&#xff0c;一般在数据库管理系统中&#xff0c;实现对数据库的并发访问&#xff1b;在编程中实现事务内存。 取自 MVCC存在被…

Editor.md-编辑器

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

[LeetCode][426]【学习日记】将二叉搜索树转化为排序的双向链表——前驱节点pre 和 当前节点cur 的使用

题目 426. 将二叉搜索树转化为排序的双向链表 将一个 二叉搜索树 就地转化为一个 已排序的双向循环链表 。 对于双向循环列表&#xff0c;你可以将左右孩子指针作为双向循环链表的前驱和后继指针&#xff0c;第一个节点的前驱是最后一个节点&#xff0c;最后一个节点的后继是第…

力扣--深度优先算法/回溯算法90.子集Ⅱ

思路分析&#xff1a; 成员变量&#xff1a; result: 用于存储最终的子集结果。path: 用于存储当前正在构建的子集。 DFS函数&#xff1a; dfs(vector<int>& nums, int start): 递归地生成子集。 从给定的start索引开始遍历数组。如果当前元素与前一个元素相同&#…

论文阅读FCN-Transformer Feature Fusion for PolypSegmentation

本文提出了一种名为Fully Convolutional Branch-TransFormer (FCBFormer)的图像分割框架。该架构旨在结合Transformer和全卷积网络&#xff08;FCN&#xff09;的优势&#xff0c;以提高结肠镜图像中息肉的检测和分类准确性。 1&#xff0c;框架结构&#xff1a; 模型采用双分…

Java项目:46 ssm005基于SSM框架的购物商城系统+jsp(含文档)

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 项目是单体ssm电商水果平台&#xff0c;包括前台商城平台及后台管理系统 前台商城系统包含首页门户、商品推荐、商品搜索、商品展示、购物车、订单流…

linux中查看目录文件(ls)用法:

查看目录下的文件&#xff1a;ls&#xff08;list&#xff09; 作用 查看目录下的内容 格式 ls -参数 操作对象参数 参数功能-l以长格形式显示文件和目录的详细信息,ls命令默认只显示名称的短格式。-d显示指定目录本身的信息,而不显示目录下的各个文件和子目录的信息。-…

【三分钟学会Redis 客户端常用命令】redis数据库、对象、字符串、列表、集合、哈希、过期设置等

目录 1. 数据库&#xff1a;2. 键&#xff1a;3. 值&#xff1a;字符串&#xff1a;列表&#xff1a;哈希&#xff1a;集合&#xff1a;有序集合&#xff1a; 4. 键过期设置&#xff1a; 1. 数据库&#xff1a; 切换数据库命令&#xff1a;select index清空数据库&#xff08;…

链表与归并排序

一个C#链表实例 链表&#xff0c;主要是“链”每个类中&#xff0c;都包含一个指向后一个节点的指针 class ListNode{public string Name { get; set; }public ListNode Next;public ListNode(string name){this.Name name;this.Next null;}}基本练成链子&#xff0c;对于插…

CSS 02

1.复合选择器 &#xff08;1.1&#xff09;后代选择器 代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0&q…

[软件工具]yolo实例分割数据集转labelme的json格式

软件界面&#xff1a; YOLO实例分割数据集转LabelMe JSON格式软件是一款功能强大的数据转换工具&#xff0c;旨在将YOLO&#xff08;You Only Look Once&#xff09;实例分割数据集转换为LabelMe的JSON格式&#xff0c;以满足不同图像标注软件之间的数据共享需求。 该软件具有…

ChatGLM:基于ChatGLM-6B使用ptuning进行微调,实现类instruction的效果

由于业务需要&#xff0c;调研下怎么训练一个虚拟角色出来&#xff0c;所以找了一些文档参考&#xff0c;其中有一个基于ChatGLM-6B使用ptuning进行微调&#xff0c;实现类instruction的效果的现成的项目&#xff0c;给大家分享下。 一、介绍 由于ChatGLM-6B 不支持instructio…

springMVC下载文件

目录 &#x1f36d;&#x1f36c;下载页面&#xff08;其实就一个超链接&#xff09; &#x1f36d;&#x1f36c;下载的具体操作 &#x1f36d;&#x1f36c;结果 承接上传文件&#xff0c;接下来看看下载文件的操作及注意事项 下载页面&#xff08;其实就一个超链接&…

EChart使用(折柱混合图,饼图)

ECharts&#xff0c;一个使用 JavaScript 实现的开源可视化库&#xff0c;可以流畅的运行在 PC 和移动设备上&#xff0c;兼容当前绝大部分浏览器&#xff0c;底层依赖矢量图形库 ZRender&#xff0c;提供直观&#xff0c;交互丰富&#xff0c;可高度个性化定制的数据可视化图表…

LLVM-3.5 —— 01记,编译 LLVM 3.5.0 clang and clang-query

包括编译&#xff1a;clang clang-tools-extra 0, prepare env sudo apt install llvm sudo apt install clang 使用最新的g 会出错。 1, source code $ git clone --recursive $ cd llvm-project $ git checkout llvmorg-3.5.0 $ cp -r ./clang ./llvm/tools/ $ mkdir llv…

机器学习-04-分类算法-02贝叶斯算法

总结 本系列是机器学习课程的系列课程&#xff0c;主要介绍机器学习中分类算法&#xff0c;本篇为分类算法与贝叶斯算法部分。 本门课程的目标 完成一个特定行业的算法应用全过程&#xff1a; 懂业务会选择合适的算法数据处理算法训练算法调优算法融合 算法评估持续调优工程…