单词拆分——LeetCode

139.单词拆分

题目

给你一个字符串 s 和一个字符串列表 wordDict 作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s 则返回 true

注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用

示例 1:

输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以由 "leet" 和 "code" 拼接成。

解题思路

  1. 动态规划:使用动态规划的思想,从左到右遍历字符串 s,判断每个前缀是否可由 wordDict 中的单词拼接而成。

  2. 状态定义:定义一个布尔数组 canBreak[i] 表示字符串 s 的前 i 个字符是否可拼接。

  3. 初始化canBreak[0] 初始化为 true,表示空字符串始终可拼接。

  4. 状态转移:对于每个索引 i(1 到 s.length()),检查 s 从索引 0 到 i-1 的每个可能前缀是否在字典中,并且前缀的结尾字符与当前索引 i 处的字符相匹配。

解题过程

  1. 初始化一个长度为 s.length() + 1 的布尔数组 canBreak,并设置 canBreak[0] 为 true

  2. 使用两层循环:外层循环遍历字符串 s 的每个索引 i。内层循环从 0 遍历到 i-1,尝试找到所有可能的前缀。

  3. 在内层循环中,如果 canBreak[j] 为 true 且 s 从索引 j 到 i 的子字符串在字典 wordDict 中,则设置 canBreak[i] 为 true 并跳出内层循环。

  4. 继续外层循环直到遍历完所有索引。

  5. 最后,返回 canBreak[s.length()],表示整个字符串 s 是否可拼接。

复杂度

  • 时间复杂度:最坏情况下,算法需要检查字符串 s 的所有子字符串是否在字典 wordDict 中。对于长度为 n 的字符串,有 O(n^2) 个子字符串,每个子字符串的查找操作的时间复杂度为 O(m)(其中 m 是字典 wordDict 的大小)。因此,总时间复杂度为 O(n^2 * m)

  • 空间复杂度:使用了一个长度为 n + 1 的布尔数组来存储中间结果,空间复杂度为 O(n)

Code

class Solution {public boolean wordBreak(String s, List<String> wordDict) {boolean[] canBreak = new boolean[s.length() + 1];canBreak[0] = true;for (int i = 1; i <= s.length(); i++) {for (int j = 0; j < i; j++) {if (canBreak[j] && wordDict.contains(s.substring(j, i))) {canBreak[i] = true;break;}}}return canBreak[s.length()];}
}

140.单词拆分II

题目

给定一个字符串 s 和一个字符串字典 wordDict ,在字符串 s 中增加空格来构建一个句子,使得句子中所有的单词都在词典中。以任意顺序 返回所有这些可能的句子。

注意:词典中的同一个单词可能在分段中被重复使用多次。

示例 1:

输入:s = "catsanddog", wordDict = ["cat","cats","and","sand","dog"]
输出:["cats and dog","cat sand dog"]

解题思路

问题定义:给定一个字符串 s 和一个字符串字典 wordDict,任务是在字符串 s 中增加空格来构建一个句子,使得句子中所有的单词都在字典 wordDict 中。这个问题可以通过回溯算法来解决。回溯算法是一种通过探索所有可能的候选解来找出所有解决方案的方法。为了避免重复计算相同子问题的解,我们使用记忆化技术来存储已经解决的子问题的解。

解题过程

  1. 初始化:创建一个 memo 哈希表来存储已经计算过的子问题的解。

  2. 递归函数:实现一个 backtrack 函数,该函数尝试在字符串 s 的不同位置添加空格,以找到所有可能的分割方式。

  3. 终止条件:如果当前索引 start 等于字符串 s 的长度,返回一个只包含空字符串的列表,表示已经到达字符串末尾。

  4. 记忆化:在 backtrack 函数中,首先检查 memo 是否已经包含了当前 start 索引的解,如果包含,则直接返回该解。

  5. 回溯搜索:遍历字符串 s 从当前索引 start 到字符串末尾的每个位置 end,检查 s 从 start 到 end 的子字符串是否在字典 wordDict 中。

  6. 递归调用:对于每个有效的子字符串,递归调用 backtrack 函数,使用 end 作为新的起始索引。

  7. 结果合并:将当前有效的子字符串与递归调用的结果合并,构建完整的句子。

  8. 存储结果:将当前 start 索引的所有可能解存储在 memo 中,以便后续使用。

复杂度

  • 时间复杂度:最坏情况下,算法需要遍历字符串 s 的所有可能的子字符串。对于长度为 n 的字符串,有 O(n^2) 个子字符串。对于每个子字符串,我们需要 O(k) 的时间来检查它是否存在于字典中,其中 k 是字典中单词的平均长度。因此,最坏情况下的时间复杂度是 O(n^2 * k)。然而,由于记忆化减少了重复计算,实际的时间复杂度可能会更低。

  • 空间复杂度:空间复杂度主要由存储子问题解的 memo 哈希表决定。在最坏的情况下,我们可能需要存储每个子问题的解,这将需要 O(n * k) 的空间。此外,递归调用栈的空间复杂度也是 O(n)。

Code

class Solution {public List<String> wordBreak(String s, List<String> wordDict) {Set<String> wordSet = new HashSet<>(wordDict);Map<Integer, List<String>> memo = new HashMap<>();return backtrack(s, 0, wordSet, memo);}private List<String> backtrack(String s, int start, Set<String> wordSet, Map<Integer, List<String>> memo) {if (start == s.length()) {return new ArrayList<>(Collections.singletonList("")); // 返回包含空字符串的列表}// 如果结果已经被计算过,直接从记忆化存储中获取结果if (memo.containsKey(start)) {return memo.get(start);}List<String> result = new ArrayList<>();for (int end = start + 1; end <= s.length(); end++) {String word = s.substring(start, end);if (wordSet.contains(word)) {List<String> subResults = backtrack(s, end, wordSet, memo);for (String subResult : subResults) {result.add(word + (subResult.isEmpty() ? "" : " " + subResult));}}}// 将计算结果存储在记忆化存储中memo.put(start, result);return result;}
}

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

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

相关文章

数据结构实验:树和二叉树(附c++源码:实现树有关算法)

目录 一、实验目的 二、问题分析及数据结构设计 三、算法设计&#xff08;伪代码表示&#xff09; 1. 输入字符序列 创建二叉链表 2. 递归前序遍历 3. 递归中序遍历 4. 递归后序遍历 5. 非递归前序遍历 6. 非递归中序遍历 7. 非递归后序遍历 8. 层次遍历 9. 求二叉…

【AI】关于AI和手机

2011 年至2015 年期间&#xff0c;全球智能手机出货量年增长率均超过两位数&#xff0c;显示出强劲的市场需 求和快速扩张趋势。然而&#xff0c;自2016 年起&#xff0c;全球智能手机用户数量趋于饱和&#xff0c;换机周期也逐 渐变长&#xff0c;市场进入存量替换阶段&#x…

Qt/C++最新地图组件发布/历时半年重构/同时支持各种地图内核/包括百度高德腾讯天地图

一、前言说明 最近花了半年时间&#xff0c;专门重构了整个地图组件&#xff0c;之前写的比较粗糙&#xff0c;有点为了完成功能而做的&#xff0c;没有考虑太多拓展性和易用性。这套地图自检这几年大量的实际项目和用户使用下来&#xff0c;反馈了不少很好的建议和意见&#…

PXE 批量安装Linux系统

目录 一、 实验环境准备 1、一台红帽版本7的主机 2、开启主机图形 3、配置网络可用 4、关闭VMware dhcp 功能 ​编辑​编辑 5、配置好本地仓库&#xff0c;方便后续下载 二、配置kickstart自动安装脚本的工具 1、 安装图形化生成kickstart自动安装脚本的工具 2、启动图…

2.MySQL库的操作

创建数据库 创建数据库的代码&#xff1a; CREATE DATABASE [IF NOT EXISTS] db_name [create_specification [,create_specification] ...];​create_specification:[DEFAULT] CHARACTER SET charset_name[DEFAULT] COLLATE collation_name 说明&#xff1a; 大写的表示关键…

【隐私保护】无证书签名方案(CLS)

一、CLS方案提出的背景 无证书签名方案&#xff08;Certificateless Signature Scheme, CLS&#xff09;是一种旨在结合公钥基础设施&#xff08;PKI&#xff09;和基于身份的加密&#xff08;IBE&#xff09;的优点&#xff0c;同时避免它们缺点的加密技术。 CLS方案的主要目标…

【网络安全渗透测试零基础入门必知必会】之什么是文件包含漏洞分类(非常详细)零基础入门到精通,收藏这一篇就够了

一、前言 这是大白给粉丝盆友们整理的网络安全渗透测试入门阶段文件包含渗透与防御第1篇。 本文主要讲解什么是文件包含漏洞、本地文件包含漏洞 喜欢的朋友们&#xff0c;记得给大白点赞支持和收藏一下&#xff0c;关注我&#xff0c;学习黑客技术。 一、什么是文件包含漏洞…

【HarmonyOS NEXT星河版开发学习】小型测试案例07-弹性布局小练习

个人主页→VON 收录专栏→鸿蒙开发小型案例总结​​​​​ 基础语法部分会发布于github 和 gitee上面&#xff08;暂未发布&#xff09; 前言 在鸿蒙&#xff08;HarmonyOS&#xff09;开发中&#xff0c;Flex布局是一种非常有用的布局方式&#xff0c;它允许开发者创建灵活且响…

Spring Boot实战:拦截器

一.拦截器快速入门 1.1了解拦截器 什么是拦截器&#xff1a; 概念 &#xff1a;拦截器是Spring框架提供的核⼼功能之⼀, 主要⽤来拦截⽤⼾的请求, 在指定⽅法前后, 根据业务需要执⾏预先设定的代码。 也就是说, 允许开发⼈员提前预定义⼀些逻辑, 在⽤⼾的请求响应前后执⾏. 也…

ThinkPHP6与金仓数据库(Kingbase)集成:模型查询的解决方案

摘要&#xff1a; ThinkPHP6是一款流行的PHP框架&#xff0c;支持多种数据库。然而&#xff0c;对于金仓数据库&#xff08;Kingbase&#xff09;这种相对小众的数据库系统&#xff0c;开发者在使用ThinkPHP6进行模型查询时可能会遇到一些兼容性问题。本文将提供一种解决方案&a…

仿推特社区源码修复版,含pc端和H5端,可以封装成app

简介&#xff1a; 新鲜出炉的仿推特社区源码修复版&#xff0c;含pc端和H5端&#xff0c;可以封装成app。这玩意绝对可以算是精品代码了。 手机h5端可以封装成软件也不错的。 推特的风格还是不错的&#xff0c;不然世界首富马斯克也不会花费440亿美金收购它了。 阅览&#…

nginx 405错误是什么意思

405错误&#xff1a;方法不被允许 当Web服务器收到一个它不支持的HTTP请求方法时&#xff0c;就会返回405错误。 原因 405错误通常是由于客户端发出了不兼容或不支持的HTTP请求方法。例如&#xff0c;客户端可能请求一个只能通过GET方法访问的资源&#xff0c;但使用了POST方…

图片转文字怎么操作?教你几招图片转文字小妙招

在日常的工作学习中&#xff0c;我们每天可能会接触到大量的图片资料&#xff0c;无论是会议纪要、书籍扫描页、还是网络上的有用信息截图&#xff0c;如果能快速将这些图片中的文字提取出来&#xff0c;无疑将极大提升我们的工作效率。下面给大家分享几种能够将图片转换成文字…

简单中间件模型

中间件是软件开发过程中架构的一个通用概念&#xff0c;其目的在于为运行的主程序提供一个供外部自定义拓展的能力。比如&#xff1a;wen服务的controller层中间件针对request请求处理的前后进行通用的扩展处理、redux中间件针对store数据获取前后的扩展处理。。。   本文简单…

OrangePi AIpro学习3 —— vscode开发昇腾DVPP程序

目录 一、VScode配置 1.1 下载和安装 1.2 安装和配置需要的插件 二、构建项目 2.1 项目架构 2.2 解决代码高亮显示 2.3 测试编译 2.4 总结出最简单的代码 2.5 vscode报错找不到头文件解决方法 三、代码简单讲解 3.1 初始化部分 3.2 拷贝数据到NPU显存中 3.3 准备裁…

python-报数(赛氪OJ)

[题目描述] 有 n 人围成一圈&#xff0c;顺序排号。 从第 1 个人开始报数&#xff08;从 1 到 3 报数&#xff09;&#xff0c;凡是报到 3 的人退出圈子&#xff0c;问最后留下的是原来的第几号的那位。输入格式&#xff1a; 初始人数 n 。输出格式&#xff1a; 最后一人的初始…

python游戏开发之五子棋游戏制作

五子棋是一种源自中国的传统棋类游戏&#xff0c;起源可以追溯到古代。它是一种两人对弈的游戏&#xff0c;使用棋盘和棋子进行。棋盘通常是一个 1515 的网格&#xff0c;棋子分为黑白两色&#xff0c;双方轮流在棋盘上落子。游戏的目标是通过在棋盘上落子&#xff0c;使自己的…

【深度学习】基于YOLOV5模型的图像识别-目标检测的性能指标详解与计算方法

目标检测是计算机视觉中的重要任务&#xff0c;主要目的是在图像中识别并定位特定的物体。YOLO&#xff08;You Only Look Once&#xff09;系列模型作为目标检测领域的代表性方法之一&#xff0c;凭借其高效和准确的特点&#xff0c;广泛应用于实际场景中。本文通过详细介绍目…

C++之移动语义与左值右值深入学习:从入门到精通!

简介 本文详细阐述了 C 中关于移动语义、左值右值等技术的基本概念和常用技巧。 问题的产生 每一项技术的诞生都是为了解决某一个问题&#xff0c;移动语义、左值右值也是一样&#xff0c;因此我们先来看看问题产生的背景。 先来看一段代码&#xff1a; #include <iost…

JavaEE: Thread类

Thread的常见构造方法 Thread的常见属性 ID 是线程的唯一标识,不同线程不会重复名称是在使用各种调试工具时会用到的状态表示线程当前所处的情况优先级高的线程理论上来说更容易被调度到关于后台线程,需要记住:JVM会在一个进程的所有非后台线程结束后,才会结束运行是否存活,即r…