LeetCode题练习与总结:单词拆分Ⅱ--140

一、题目描述

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

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

示例 1:

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

示例 2:

输入:s = "pineapplepenapple", wordDict = ["apple","pen","applepen","pine","pineapple"]
输出:["pine apple pen apple","pineapple pen apple","pine applepen apple"]
解释: 注意你可以重复使用字典中的单词。

示例 3:

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

提示:

  • 1 <= s.length <= 20
  • 1 <= wordDict.length <= 1000
  • 1 <= wordDict[i].length <= 10
  • s 和 wordDict[i] 仅有小写英文字母组成
  • wordDict 中所有字符串都 不同

二、解题思路

这个问题是一个典型的动态规划问题,可以使用回溯法来解决。解题思路如下:

  1. 动态规划预处理:首先,我们可以用动态规划的方法预处理字符串s,创建一个布尔数组dp,其中dp[i]表示s中前i个字符组成的字符串是否可以被空格拆分为一个或多个在字典中出现的单词。这样我们可以快速判断一个子串是否可被分割。

  2. 回溯法搜索:然后,我们使用回溯法来找出所有可能的句子。我们从字符串的开始进行,对于每一个位置,我们尝试用字典中的单词进行匹配,如果匹配成功,则将这个单词加入到当前的句子中,并递归地尝试匹配后续的字符串。当递归到达字符串末尾时,我们就找到了一个有效的句子。

  3. 去重:由于字典中可能存在重复的单词,我们需要确保在回溯的过程中不会产生重复的句子。

三、具体代码

import java.util.*;

public class Solution {
    public List<String> wordBreak(String s, List<String> wordDict) {
        // 预处理,使用set提高查找效率
        Set<String> wordSet = new HashSet<>(wordDict);
        // dp[i] 表示s的前i个字符是否可以由字典中的单词组成
        boolean[] dp = new boolean[s.length() + 1];
        dp[0] = true;
        
        // 动态规划填表
        for (int i = 1; i <= s.length(); i++) {
            for (int j = 0; j < i; j++) {
                if (dp[j] && wordSet.contains(s.substring(j, i))) {
                    dp[i] = true;
                    break;
                }
            }
        }
        
        // 如果整个字符串都不能拆分,直接返回空列表
        if (!dp[s.length()]) {
            return new ArrayList<>();
        }
        
        // 使用回溯法找出所有可能的句子
        List<String> sentences = new ArrayList<>();
        backtrack(s, wordSet, dp, 0, new StringBuilder(), sentences);
        return sentences;
    }
    
    private void backtrack(String s, Set<String> wordSet, boolean[] dp, int start, StringBuilder sentence, List<String> sentences) {
        if (start == s.length()) {
            sentences.add(sentence.toString().trim());
            return;
        }
        
        for (int end = start + 1; end <= s.length(); end++) {
            if (dp[end] && wordSet.contains(s.substring(start, end))) {
                int prevLength = sentence.length();
                sentence.append(s, start, end).append(" ");
                backtrack(s, wordSet, dp, end, sentence, sentences);
                sentence.setLength(prevLength); // 回溯
            }
        }
    }
    
    // 测试代码
    public static void main(String[] args) {
        Solution solution = new Solution();
        List<String> wordDict = Arrays.asList("cat", "cats", "and", "sand", "dog");
        System.out.println(solution.wordBreak("catsanddog", wordDict));
    }
}

四、时间复杂度和空间复杂度

1. 时间复杂度
  • 动态规划填表:对于字符串s的每个位置i,我们可能需要检查从0i-1的所有位置j,以确定是否存在一个单词可以匹配s[j:i]。因此,动态规划的时间复杂度为O(n^2),其中n是字符串s的长度。
  • 回溯法搜索:在最坏的情况下,我们可能需要生成所有可能的句子,每个句子都是由字典中的单词组成的。如果字典中有m个单词,那么最坏情况下的时间复杂度为O(m^n),因为每个位置都可能尝试字典中的每个单词。

综上所述,总的时间复杂度为O(n^2 + m^n)

2. 空间复杂度
  • 动态规划数组dp:需要O(n)的空间来存储布尔值,表示字符串s的前i个字符是否可以由字典中的单词组成。
  • 回溯过程中的递归栈:在最坏的情况下,递归的深度可能达到n,因此递归栈需要O(n)的空间。
  • wordSet:需要O(m)的空间来存储字典中的单词,其中m是字典中单词的数量。
  • 存储结果的列表sentences:在最坏的情况下,可能需要O(m^n)的空间来存储所有可能的句子。

综上所述,总的空间复杂度为O(n + m + m^n)

注意:在实际应用中,由于字典中的单词数量和长度有限,以及字符串s的长度也有限,所以m^n的空间复杂度是非常理论化的,实际上可能不会有这么多组合。同样,时间复杂度中的m^n也是理论上的最坏情况,实际运行时间可能会因为字典中单词的长度和字符串s的特定内容而有所不同。

五、总结知识点

1. 动态规划(Dynamic Programming)

  • 动态规划是一种算法设计技术,用于解决多阶段决策问题,通过将问题分解为更小的子问题,并将这些子问题的解存储起来以避免重复计算,从而提高效率。
  • 在这个问题中,动态规划用于预处理字符串s,以确定哪些子串可以被字典中的单词组成。

2. 回溯法(Backtracking)

  • 回溯法是一种试探性的算法,用于寻找所有可能的解决方案。它尝试构建一个解决方案,一旦确定当前的解决方案不满足条件,就回溯到上一步,换一种方式继续尝试。
  • 在这个问题中,回溯法用于构建所有可能的句子组合。

3. 哈希集合(HashSet)

  • 哈希集合是一种数据结构,用于存储不重复的元素,并提供快速的查找操作。
  • 在这个问题中,哈希集合用于存储字典中的单词,以便快速判断一个子串是否为字典中的单词。

4. 字符串处理(String Manipulation)

  • 代码中使用了StringStringBuilder类来处理字符串,包括子串的提取、字符串的拼接和修改等。

5. 递归(Recursion)

  • 递归是一种算法结构,其中一个函数直接或间接调用自身。
  • 在这个问题中,递归用于实现回溯法,通过递归调用backtrack函数来构建所有可能的句子。

6. 列表(ArrayList)

  • 列表是一种可变的序列,用于存储集合中的元素。
  • 在这个问题中,列表用于存储所有可能的句子。

7. 布尔数组(Boolean Array)

  • 布尔数组用于存储布尔值,以表示某个条件是否满足。
  • 在这个问题中,布尔数组dp用于标记字符串s的每个前缀是否可以被字典中的单词组成。

8. 边界条件处理

  • 代码中包含了边界条件的处理,例如当整个字符串都不能被拆分时,直接返回空列表。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

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

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

相关文章

昇思25天学习打卡营第10天|基于MindSpore的GPT2文本摘要

学AI还能赢奖品&#xff1f;每天30分钟&#xff0c;25天打通AI任督二脉 (qq.com) 基于MindSpore的GPT2文本摘要 %%capture captured_output # 实验环境已经预装了mindspore2.2.14&#xff0c;如需更换mindspore版本&#xff0c;可更改下面mindspore的版本号 !pip uninstall m…

Duix - 硅基数字人SDK

简介 Introduction DUIX(Dialogue User Interface System)是硅基智能打造的AI数字人智能交互平台。通过将数字人交互能力开源,开发者可自行接入多方大模型、语音识别(ASR)、语音合成(TTS)能力,实现数字人实时交互,并在Android和iOS多终端一键部署,让每个开发者可轻松…

2、逻辑回归

1. 为什么要叫逻辑回归? 逻辑回归模型的名称可能会引起一些混淆,因为它名字中包含了"回归"这个词,但实际上它是一种用于解决分类问题的模型,而不是回归问题。 逻辑回归最初是从线性回归模型演变而来的。线性回归用于预测连续的数值输出,逻辑回归则是在线性回归…

shell 脚本中断问题定位

shell 脚本中断问题定位 1 介绍2 定位方法2.1 查看脚本的退出状态码2.2 查看系统日志文件2.3 使用journalctl工具2.4 使用dmesg命令2.5 检查脚本自身的日志记录2.6 使用图形界面工具2.7 配置和使用集中式日志管理系统 参考 1 介绍 shell 脚本运行&#xff0c;一段时间后&#…

SQL注入和防御方法

SQL注入是一种攻击手段&#xff0c;通过在SQL查询中插入恶意SQL代码片段&#xff0c;欺骗数据库服务器执行非授权的数据库操作。这种攻击可能导致数据泄露、篡改或丢失。为了防范SQL注入&#xff0c;可以采取以下几种策略&#xff1a; 1.使用预编译语句&#xff08;Prepared St…

戴尔笔记本重装系统?笔记本卡顿失灵?一键重装系统!

随着科技的快速发展&#xff0c;笔记本电脑已成为我们日常生活和工作中不可或缺的工具。然而&#xff0c;随着时间的推移&#xff0c;笔记本可能会遇到各种问题&#xff0c;如系统卡顿、失灵等。这时&#xff0c;重装系统往往是一个有效的解决方案。本文将详细介绍如何在戴尔笔…

stm32-USART通信

什么是usart&#xff1f;和其他通信又有什么区别&#xff1f; 如下图&#xff1a; USART是一种用于串行通信的设备&#xff0c;可以在同步和异步模式下工作。 usart有两根数据线&#xff0c;一根发送线&#xff08;tx&#xff09;一根接收线&#xff08;rx&#xff09;&#x…

2、Redis持久化与高可用架构

一、Redis 持久化 RDB 快照&#xff08;Snapshot&#xff09; 基本概念&#xff1a;RDB&#xff08;Redis DataBase&#xff09;快照是将 Redis 内存中的数据在某个时间点保存到磁盘中的一种持久化方式&#xff0c;默认保存到 dump.rdb 的二进制文件中。通过 RDB 快照&#xff…

Pytorch课程论文设计参考

Pytorch下基于卷积神经网络的手写数字识别 论文格式 利用wps初步美化论文格式教程 wps论文格式变的的原因 格式变的根本原因是word为流式文件&#xff0c;就算同是word同一个版本不同电脑也会有可能变&#xff0c;字体变是因为没有嵌入字体然后观看的那台没有这个字体。 一、…

Excel单元格输入逐字动态提示可选输入效果制作

Excel单元格输入逐字动态提示可选输入效果制作。INDEX函数整理动态列表&#xff0c;再配合IF函数干净界面&#xff0c;“数据验证”完成点选。 (笔记模板由python脚本于2024年06月27日 22:26:14创建&#xff0c;本篇笔记适合喜欢用Excel处理数据的coder翻阅) 【学习的细节是欢悦…

视频监控管理平台LntonCVS智能视频监控平台系统详细介绍

安防视频监控平台LntonCVS以其卓越的灵活性和便捷的部署特性在众多同类产品中脱颖而出。它不仅支持多种主流标准协议&#xff0c;如国标GB28181、RTSP/Onvif、RTMP等&#xff0c;还兼容了海康Ehome、海大宇等厂家的私有协议和SDK接入&#xff0c;为用户提供了更加丰富的选择。 …

什么是有效的电子签名?PDF电子签名怎样具备法律效力?

电子签名逐渐成为商务文书和法律文件中不可或缺的一部分。《电子签名法》自2005年4月1日起施行&#xff0c;这一立法是中国信息化法律的重要里程碑&#xff0c;为电子签名应用奠定了法律基础。电子签名不仅仅是一种技术手段&#xff0c;更是一种法律认可的签名形式。那么究竟什…

【vue3】【vant】 移动端中国传统文化和民间传说案例

更多项目点击&#x1f446;&#x1f446;&#x1f446;完整项目成品专栏 【vue3】【vant】 移动端中国传统文化和民间传说案例 获取源码方式项目说明&#xff1a;其中功能包括项目包含&#xff1a;项目运行环境运行截图和视频 获取源码方式 加Q群&#xff1a;632562109项目说…

clickhouse count和uniqCombined

count(distinct ) 和 uniqCombined 获取去重后的总数。 去重&#xff1a;order by distinct argMax group by 哪个好&#xff1f;&#xff1f; clickhouse数据去重函数介绍&#xff08;count distinct&#xff09;_clickhouse distinct-CSDN博客

重生之我要学后端0--HTTP协议和RESTful APIs

http和RESTful APIs HTTP协议RESTful APIs设计RESTful API设计实例 HTTP协议 HTTP&#xff08;超文本传输协议&#xff09;是用于分布式、协作式和超媒体信息系统的应用层协议。它是网页数据通讯的基础。工作原理简述如下&#xff1a; 客户端请求&#xff08;Request&#xf…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 特殊加密算法(200分) - 三语言AC题解(Python/Java/Cpp)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; &#x1f…

Python和tkinter实现的字母记忆配对游戏

Python和tkinter实现的字母记忆配对游戏 因为这个小游戏用到了tkinter&#xff0c;先简要介绍一下它。tkinter是Python的标准GUI(图形用户界面)库&#xff0c;它提供了一种简单而强大的方式来创建图形界面应用程序。它提供了创建基本图形界面所需的所有工具&#xff0c;同时保…

生产者发送数据,kafka服务器接收数据异常的问题记录

现象&#xff1a; 某个客户要求审计日志用kafka的方式传输给他们&#xff0c;使用了第三方的librdkafka库来开发。 往客户提供的kafka服务器上的一个topic发送数据&#xff0c;这个topic有三个分区&#xff0c;客户反馈接收到的数据和发送端发送的实际数量对不上&#xff0c;他…

Elasticsearch环境搭建|ES单机|ES单节点模式启动|ES集群搭建|ES集群环境搭建

文章目录 版本选择单机ES安装与配置创建非root用户导入安装包安装包解压配置JDK环境变量配置single-node配置JVM参数后台启动|启动日志查看启动成功&#xff0c;访问终端访问浏览器访问 Kibana安装修改配置后台启动|启动日志查看浏览器访问 ES三节点集群搭建停止es服务域名配置…

平板WPS转换的PDF文件保存位置解析

在日常工作和生活中&#xff0c;我们经常需要将文档转换成PDF格式进行分享&#xff0c;以确保接收者能够无障碍地查看文件内容&#xff0c;不受软件版本或操作系统的限制。WPS作为一款功能强大的办公软件&#xff0c;也提供了文档转换为PDF的功能。然而&#xff0c;有时在转换并…