题目:

1、我的写法(超时)

从题面自然想到先用回溯算法把words的全排列先算出来,然后遍历字符串s一次将符合条件的位置加入结果

全排列计算所有可能字符串算法写法:

这是一个模板用于所有全排列算法的情况,本质思想是回溯。四个参数:words代表候选单词数组,path代表已经选过的路径,used代表当前元素有没有使用过,result代表结果这里用了set去重

在每次回溯开始前先判断,当前路径有没有包含所有候选单词,如果都包含了的话就加入结果。

从当前path开始算,尝试所有可能性,把没用到的元素加入path递归,然后恢复数据开始下一次回溯

这是我在外层调用的方法,最后显示超时了,超时原因在于当words长度过长时,递归回溯的方法复杂度不好控制,过于耗时

完整代码:

class Solution {

    public List<Integer> findSubstring(String s, String[] words) {

        //全排列找出words能拼接成的所有字符串

        Set<String> concatStr = new HashSet<>();

        boolean[] used = new boolean[words.length];

        backTrack(words, new ArrayList<>(), used, concatStr);

        //遍历字符串s,与所有可能的拼接结果对比,找到符合的结果

        int wordLen = 0;

        List<Integer> result = new ArrayList<>();

        for(int i = 0; i < words.length; i++) {

            wordLen += words[i].length();

        }

        for(int i = 0; i <= s.length() - wordLen; i++) {

            if(concatStr.contains(s.substring(i, i + wordLen))) {

               result.add(i);

            }

        }

        return result;

    }

    private void backTrack(String[] words, List<String> path, boolean[] used, Set<String> result) {

        if(path.size() == words.length) {

            result.add(String.join("", path));

        }

        for(int i = 0; i < words.length; i++) {

            if(used[i] == false) {

                //如果没有被用过加入path中

                used[i] = true;

                path.add(words[i]);

                //递归回溯

                backTrack(words, path, used, result);

                //撤销操作,去掉最后一个元素并标记为未使用

                used[i] = false;

                path.remove(path.size() - 1);

            }

        }

    }

}

2、官方解法

不需要递归回溯,用到了异位字符串思想

官解的思路类似于找到字符串中的字母异位词,只不过它从之前的字母异位变成了字符串异位。注意,体面中words每个单词的长度都是相等的,所以我们是可以等长的去划分子串的,这样划分之后用哈希表differ去划分。

遍历一遍数组,从0开始,直到最后无法满足长度为止。每次循环,都初始化一个哈希表用来记录划分后的单词出现频率和words的误差,等同于之前字符串中找到字母异位词的做法,只不过这里不再是字母而是一个个长度相等的字符串

完整代码:

class Solution {

    public List<Integer> findSubstring(String s, String[] words) {

        List<Integer> res = new ArrayList<Integer>();

        int m = words.length, n = words[0].length(), ls = s.length();

        for (int i = 0; i < n; i++) {

            if (i + m * n > ls) {

                break;

            }

            Map<String, Integer> differ = new HashMap<String, Integer>();

            for (int j = 0; j < m; j++) {

                String word = s.substring(i + j * n, i + (j + 1) * n);

                differ.put(word, differ.getOrDefault(word, 0) + 1);

            }

            for (String word : words) {

                differ.put(word, differ.getOrDefault(word, 0) - 1);

                if (differ.get(word) == 0) {

                    differ.remove(word);

                }

            }

            for (int start = i; start < ls - m * n + 1; start += n) {

                if (start != i) {

                    String word = s.substring(start + (m - 1) * n, start + m * n);

                    differ.put(word, differ.getOrDefault(word, 0) + 1);

                    if (differ.get(word) == 0) {

                        differ.remove(word);

                    }

                    word = s.substring(start - n, start);

                    differ.put(word, differ.getOrDefault(word, 0) - 1);

                    if (differ.get(word) == 0) {

                        differ.remove(word);

                    }

                }

                if (differ.isEmpty()) {

                    res.add(start);

                }

            }

        }

        return res;

    }

}

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

操作系统【1】【硬件结构】【操作系统结构】

一、CPU如何执行程序&#xff1f; 提纲 图灵机工作方式冯诺依曼模型线路位宽CPU位宽程序执行基本过程执行具体过程 1. 图灵机工作方式 图灵机可以视作“一台带规则的自动草稿机” 图灵机基本组成&#xff1a; 纸带&#xff08;内存&#xff09;&#xff1a;连续格子组成&…

SQLite与MySQL:嵌入式与客户端-服务器数据库的权衡

SQLite与MySQL&#xff1a;嵌入式与客户端-服务器数据库的权衡 在开发应用程序时&#xff0c;数据库选择是一个至关重要的决策&#xff0c;它会影响应用的性能、可扩展性、部署难度和维护成本。SQLite和MySQL是两种广泛使用的关系型数据库管理系统&#xff0c;它们各自针对不同…

CppCon 2018 学习:Smart References

“强类型别名”&#xff08;strong typedefs&#xff09; 的动机和实现&#xff0c;配合一个简单例子说明&#xff1a; 动机&#xff08;Motivation&#xff09; 用 using filename_t string; 和 using url_t string; 来区分不同的字符串类型&#xff08;比如文件名和网址&…

高性能高准确度的CPU电压与温度监测软件HWInfo

&#x1f5a5;️ 一、软件概述 Windows版&#xff1a;图形化界面&#xff0c;支持实时监控&#xff08;温度、电压、风扇转速等&#xff09;、基准测试及报告生成&#xff0c;兼容Windows XP至Windows 11系统。Linux版&#xff1a;命令行工具&#xff0c;由openSUSE社区维护&a…

H3C WA6322 AP版本升级

1、查看当前版本&#xff1a;R2444P01 2、官网下载升级文件&#xff1a; WA6300系列版本说明H3C WA6300系列(适用于WA6330、 WA6322、WA6320H、WA6320、 WTU630H、WTU630、WA6330-LI、WA6320-C、WA6320-D、WA6320H-LI、WA6338、WA6322H、WTU632H-IOT、WAP922E、WAP923、WA6320…

用 YOLOv8 + DeepSORT 实现目标检测、追踪与速度估算

【导读】 目标检测与追踪技术是计算机视觉领域最热门的应用之一&#xff0c;广泛应用于自动驾驶、交通监控、安全防护等场景。今天我们将带你一步步实现一个完整的项目&#xff0c;使用YOLOv8 DeepSORT实现目标检测、追踪与速度估算。>>更多资讯可加入CV技术群获取了解…

Python实例题:基于 Python 的简单聊天机器人

Python实例题 题目 基于 Python 的简单聊天机器人 要求&#xff1a; 使用 Python 构建一个聊天机器人&#xff0c;支持以下功能&#xff1a; 基于规则的简单问答系统关键词匹配和意图识别上下文记忆功能支持多轮对话可扩展的知识库 使用tkinter构建图形用户界面。实现至少 …

相机:Camera原理讲解(使用OpenGL+QT开发三维CAD)

相机为三维场景提供了灵活便捷的视角变换和交互能力&#xff0c;通过相机操作可以实现全方位、各角度的场景浏览。 怎样在三维场景中引入相机&#xff0c;怎样处理和实现视角的放缩、移动、旋转&#xff1f;在视角旋转时以指定目标为中心又该怎样处理&#xff1f; 原文&#…

开源的虚拟电厂预测数据:资源、应用与挑战

引言 虚拟电厂(Virtual Power Plant, VPP)是一种通过聚合分布式能源资源(如太阳能、风能、储能系统、电动汽车和可控负荷)来优化电力系统运行的数字化能源管理平台。准确的预测数据是虚拟电厂高效运行的关键,而开源数据为研究者和企业提供了低成本、高透明度的解决方案。…

IDE全家桶专用快捷键----------个人独家分享!!

给大家分享一下我个人整理的快捷键&#xff0c;其中包含对电脑的操作&#xff0c;以及在编写代码时的操作&#x1f680;Window系列1 WindowsR 开启运行对话框--->输入cmd启动黑窗口​2 WindowsE 快速打开我的电脑 ​3 WindowsL 电脑锁屏 ​4 WindowsD 显示/恢复桌面 ​5 Win…

人工智能概念:RNN中的基础Encoder-Decoder框架

文章目录一、序列&#xff08;Seq2Seq&#xff09;转换的核心架构二、Encoder-Decoder框架基础原理2.1 整体工作流程2.2 编码器&#xff08;Encoder&#xff09;详解2.3 解码器&#xff08;Decoder&#xff09;工作机制与缺陷三、基础框架的核心缺陷分析&#xff08;以"欢…

R 列表:深入解析与高效应用

R 列表&#xff1a;深入解析与高效应用 引言 在R语言中&#xff0c;列表&#xff08;List&#xff09;是一种非常重要的数据结构&#xff0c;它允许我们将不同类型的数据组合在一起。列表在数据分析和统计建模中扮演着至关重要的角色。本文将深入探讨R列表的概念、创建方法、…

uniapp 国密sm2加密

1. uniapp 国密sm2加密 在uniapp中使用国密SM2算法进行加密解密&#xff0c;你可以通过安装第三方库miniprogram-sm-crypto来实现。这个库提供了SM2、SM3和SM4算法的实现&#xff0c;可以在小程序和uniapp项目中使用。 1.1. 安装miniprogram-sm-crypto 首先&#xff0c;你需要…

07_持续集成与部署:DevOps的核心引擎

07_持续集成与部署:DevOps的核心引擎 引言 在快速迭代的软件开发时代,持续集成(CI)与持续部署(CD)已成为企业提升竞争力的关键。通过自动化构建、测试和部署流程,CI/CD能够显著缩短交付周期,提高软件质量,降低发布风险。本文将深入探讨CI/CD的核心理念、实施路径与最…

电脑休眠设置

Dont Sleep的意思就是“不要睡觉”&#xff0c;用在电脑里就是“阻止休眠”的意思。但这款软件其实有“阻止休眠”和“允许休眠”两个功能。 阻止休眠时可以选择事件&#xff0c;是计时器、电池、CPU、网络这几个事件进行触发阻止休假的功能。 允许休眠也可以根据自己的需求进行…

蓝牙墨水屏上位机学习(3)

main.js中sendimg()函数学习&#xff0c;对应发送图片按钮函数代码如下&#xff1a;async function sendimg() {const canvasSize document.getElementById(canvasSize).value;const ditherMode document.getElementById(ditherMode).value;const epdDriverSelect document.…

Linux应用基础

1. 基础概念 1.1 系统调用 系统调用实际上是Linux内核为上层应用程序提供的API接口&#xff0c;方便应用程序进行调用&#xff0c;类似于SVC。 1.2 库函数 库函数是应用层里边的东西&#xff0c;在系统调用的上层&#xff0c;通常以动态库文件&#xff08;.so&#xff09;形式…

【时间序列数据处理的噩梦与救赎:一次复杂数据可视化问题的深度复盘】

时间序列数据处理的噩梦与救赎&#xff1a;一次复杂数据可视化问题的深度复盘 创建时间: 2025/7/3 技术栈: Vue 3 TypeScript UniApp ECharts 问题级别: &#x1f534; 系统性架构问题 &#x1f3af; 引言&#xff1a;当简单需求变成技术噩梦 “老哥&#xff0c;这个图表时…

Redis--黑马点评--基于stream消息队列的秒杀优化业务详解

基于redis的stream结构作为消息队列&#xff0c;实现异步秒杀下单 需求&#xff1a; 创建一个Stream类型的消息队列&#xff0c;名为stream.oreders 修改之前的秒杀下单Lua脚本&#xff0c;在认定有抢够资格后&#xff0c;直接向stream.orders中添加消息&#xff0c;内容包括…

Zephyr RTOS 防止中断影响数据写入

目录 概述 1 中断保护核心策略 1.1 中断锁定/解锁 (IRQ Locking) 1.2 自旋锁 (Spin Locks) 2 高级保护技术 2.1 双重缓冲技术 2.2 RCU (Read-Copy-Update) 模式 3 中断安全数据写入模式 3.1 FIFO队列保护 3.2 原子操作保护 4 性能优化策略 4.1 分区数据保护 4.2 中断…