【动态规划】139. 单词拆分

news2024/10/5 17:16:43

139. 单词拆分

难度:中等
力扣地址:https://leetcode.cn/problems/word-break/description/

在这里插入图片描述

问题描述

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

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

示例 1:

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

示例 2:

输入: s = “applepenapple”, wordDict = [“apple”, “pen”]
输出: true
解释: 返回 true 因为 “applepenapple” 可以由 “apple” “pen” “apple” 拼接成。
注意,你可以重复使用字典中的单词。

示例 3:

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

提示:

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

问题分析

套公式(完全背包)之前,需要先回顾一下完全背包问题,并结合本道题内容进行适配。

在这里插入图片描述
接着我们回顾一下完全背包问题的求解过程,这个非常基础,也非常重要。
在这里插入图片描述
理解完全背包问题以后,接下来就是真的套公式了,最关键的地方还是在于如何定义状态转移方程,这个过程也比较难,需要理解题目的意思,并且清楚状态转移的条件。
在这里插入图片描述

解题代码

分析在前面已经进行介绍,这里我们逐行解释代码的作用,如果有任何疑问,欢迎后面留言。

C++ 解题代码

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        // 将字典中的单词存储到 unordered_set 中以加快查找速度
        unordered_set<string> wordSet(wordDict.begin(), wordDict.end());

        // 动态规划数组 dp,其中 dp[i] 表示 s 的前 i 个字符是否可以被拆分成字典中的单词
        vector<bool> dp(s.size() + 1, false);

        // 初始化:空字符串总是可以被拆分的
        dp[0] = true; 

        // 遍历字符串 s 的每一个字符位置 i
        for (int i = 1; i <= s.size(); ++i) {
            // 检查从 j 到 i 的子字符串 s[j:i] 是否在字典中
            for (int j = 0; j < i; ++j) {
                string target = s.substr(j, i - j);
                // 如果 dp[j] 为 true,且目标子串在字典中
                if (dp[j] && wordSet.find(target) != wordSet.end()) {
                    // 则将 dp[i] 设为 true,表示前 i 个字符可以被拆分
                    dp[i] = true;
                    // 找到一个合法的拆分,跳出内层循环
                    break;
                }
            }
        }

        // 返回 dp[s.size()],表示整个字符串 s 是否可以被拆分成字典中的单词
        return dp[s.size()];
    }
};

对应的 Java 版本为:

class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        // 将字典中的单词存储到 HashSet 中以加快查找速度
        Set<String> wordSet = new HashSet<>(wordDict);

        // 动态规划数组 dp,其中 dp[i] 表示 s 的前 i 个字符是否可以被拆分成字典中的单词
        boolean[] dp = new boolean[s.length() + 1];

        // 初始化:空字符串总是可以被拆分的
        dp[0] = true;

        // 遍历字符串 s 的每一个字符位置 i
        for (int i = 1; i <= s.length(); ++i) {
            // 检查从 j 到 i 的子字符串 s[j:i] 是否在字典中
            for (int j = 0; j < i; ++j) {
                String target = s.substring(j, i);
                // 如果 dp[j] 为 true,且目标子串在字典中
                if (dp[j] && wordSet.contains(target)) {
                    // 则将 dp[i] 设为 true,表示前 i 个字符可以被拆分
                    dp[i] = true;
                    // 找到一个合法的拆分,跳出内层循环
                    break;
                }
            }
        }

        // 返回 dp[s.length()],表示整个字符串 s 是否可以被拆分成字典中的单词
        return dp[s.length()];
    }
}

对应的python版本代码为:

class Solution:
    def wordBreak(self, s: str, wordDict: list[str]) -> bool:
        # 将字典中的单词存储到 set 中以加快查找速度
        wordSet = set(wordDict)

        # 动态规划数组 dp,其中 dp[i] 表示 s 的前 i 个字符是否可以被拆分成字典中的单词
        dp = [False] * (len(s) + 1)

        # 初始化:空字符串总是可以被拆分的
        dp[0] = True

        # 遍历字符串 s 的每一个字符位置 i
        for i in range(1, len(s) + 1):
            # 检查从 j 到 i 的子字符串 s[j:i] 是否在字典中
            for j in range(i):
                target = s[j:i]
                # 如果 dp[j] 为 True,且目标子串在字典中
                if dp[j] and target in wordSet:
                    # 则将 dp[i] 设为 True,表示前 i 个字符可以被拆分
                    dp[i] = True
                    # 找到一个合法的拆分,跳出内层循环
                    break

        # 返回 dp[len(s)],表示整个字符串 s 是否可以被拆分成字典中的单词
        return dp[len(s)]

总结

本次例子中我们不再通过若干个例子介绍拆分过程,主要强调如何套公式,但是这些都是建立在对原版的完全背包问题熟悉的基础上,如果对完全背包问题不太熟悉,建议参考本博客中介绍的完全背包问题 4 步解题法,接着再套到这个题中理解。

Smileyan
2024.06.30 20:37

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

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

相关文章

App托管服务分发平台 index-uplog.php 文件上传致RCE漏洞复现

0x01 产品简介 App托管服务分发平台是一个为开发者提供全面、高效、安全的应用程序托管、分发和推广服务的平台。开发者可以将自己开发的应用程序上传到平台上,平台会对上传的应用程序进行审核,确保应用的质量和安全性。平台会根据开发者的要求,将应用分发到不同的应用市场…

【鸿蒙学习笔记】位置设置

官方文档&#xff1a;位置设置 目录标题 align&#xff1a;子元素的对齐方式direction&#xff1a;官方文档没懂&#xff0c;看图理解吧 align&#xff1a;子元素的对齐方式 Stack() {Text(TopStart)}.width(90%).height(50).backgroundColor(0xFFE4C4).align(Alignment.TopS…

C++学习全教程(Day2)

一、数组 在程序中为了处理方便,常常需要把具有相同类型的数据对象按有序的形式排列起来&#xff0c;形成“一组”数据&#xff0c;这就是“数组”(array&#xff09; 数组中的数据&#xff0c;在内存中是连续存放的&#xff0c;每个元素占据相同大小的空间&#xff0c;就像排…

matrixone集群搭建、启停、高可用扩缩容和连接数据库

1. 部署 Kubernetes 集群 由于 MatrixOne 的分布式部署依赖于 Kubernetes 集群&#xff0c;因此我们需要一个 Kubernetes 集群。本篇文章将指导你通过使用 Kuboard-Spray 的方式搭建一个 Kubernetes 集群。 准备集群环境 对于集群环境&#xff0c;需要做如下准备&#xff1a…

25 防火墙基础操作

1 防火墙进入WEB页面操作 华三防火墙的默认用户:admin/密码:admin 将IP地址改在同一网段的信息 在防火墙的管理地址 GE/0/0/1&#xff1a;192.168.0.1 主机的地址是:192.168.0.101 思考一下为什么Ping不通 security-zone name Management import interface GigabitEthernet1/…

Git安装与使用及整合IDEA使用的详细教程

1. 版本控制软件介绍 版本控制软件提供完备的版本管理功能&#xff0c;用于存储、追踪目录&#xff08;文件夹&#xff09;和文件的修改历史&#xff0c;是软件开发者的必备工具&#xff0c;是软件公司的基础设施。版本控制软件的最高目标&#xff0c;是支持软件公司的配置管理…

2 z变换与离散时间傅里叶变换

目录 序列的z变换 z变换的定义 常用典型序列的z变换 序列类型与z变换的收敛域 序列的分类 X(z)的极点与收敛域 单边序列 双边序列 z变换的性质 线性 序列移位 单边序列 双边序列 z域尺度变换 序列乘以n 复共轭序列的z变换 初值定理 终值定理 时域卷积定理 …

Suno体验记录

五月初的时候初体验了一下Suno v3&#xff0c;当时整体觉得还不错&#xff0c;操作简单&#xff0c;生成快&#xff0c;歌曲也算好听。当时就截止到这里了。最近发现有了一些新的更新&#xff0c;觉得可以整理记录一下。 1. 简单介绍 免费用户一天50积分&#xff08;不累计&a…

python 压缩数据

requests 是 Python 中一个非常流行的 HTTP 库&#xff0c;用于发送各种 HTTP 请求。下面是一个使用 requests 库发送简单 GET 请求和 POST 请求的示例&#xff1a; 首先&#xff0c;确保你已经安装了 requests 库。如果还没有安装&#xff0c;可以使用 pip 进行安装&#xff…

在线教育项目(一):如何防止一个账号多个地方登陆

使用jwt做验证&#xff0c;使用账号作为redis中的key,登录的时候生成token放到redis中&#xff0c;每次申请资源的时候去看token 有没有变&#xff0c;因为token每次登录都会去覆盖&#xff0c;只要第二次登录token就不一样了

【接口自动化测试】第四节.实现项目核心业务的单接口自动化测试

文章目录 前言一、登录单接口自动化测试 1.1 登录单接口文档信息 1.2 登录成功 1.3 登录失败&#xff08;用户名为空&#xff09;二、数据驱动的实现 2.1 json文件实现数据驱动总结 前言 一、登录单接口自动化测试 1.1 登录单接口文档信息 需求&#xff1…

实验6 形态学图像处理

1. 实验目的 ①掌握数字图像处理中&#xff0c;形态学方法的基本思想&#xff1b; ②掌握膨胀、腐蚀、开运算、闭运算等形态学基本运算方法&#xff1b; ③能够利用形态学基本运算方法&#xff0c;编程实现图像去噪&#xff0c;边界提取等功能。 2. 实验内容 ①调用Matlab /…

数据资产铸就市场竞争优势:运用先进的数据分析技术,精准把握市场脉搏,构建独特的竞争优势,助力企业实现市场领先地位,赢得持续成功

目录 一、引言 二、数据资产的重要性 三、先进数据分析技术的应用 1、大数据分析技术 2、人工智能与机器学习 3、数据可视化技术 四、精准把握市场脉搏 1、深入了解客户需求 2、预测市场趋势 3、优化资源配置 五、构建独特的竞争优势 1、定制化产品和服务 2、精准营…

计算机网络原理及应用

第一章 计算机网络概述 【1】局域网 局域网是指在某一区域内由多台计算机互联而成的计算机通信网络。 【1】互通 两个网络之间可以交换数据。 第二章 计算机网络的体系结构 【1】语义 何时发出何种控制信息&#xff0c;完成何种动作以及做出何种响应。 【2】简述网络协…

1Panel运维利器:功能详解与实操指南

官网地址:https://1panel.cn/ 1Panel简介 1Panel是杭州飞致云信息科技有限公司旗下产品&#xff0c;是一款现代化、开源的Linux服务器运维管理面板&#xff0c;于2023年3月推出。 名称&#xff1a;1Panel开源Linux面板 所属公司&#xff1a;杭州飞致云信息科技有限公司 编写语…

【C++】————string基础用法及部分函数底层实现

作者主页&#xff1a; 作者主页 本篇博客专栏&#xff1a;C 创作时间 &#xff1a;2024年6月30日 前言&#xff1a; 本文主要介绍STL容器之一 ---- string&#xff0c;在学习C的过程中&#xff0c;我们要将C视为一个语言联邦&#xff08;摘录于Effective C 条款一&#x…

智能旅行规划的未来:大模型与形式化验证的融合

我们在做旅行规划时面对众多的目的地选择、复杂的交通连接、预算限制以及个人偏好等多重因素&#xff0c;即使是最有经验的旅行者也可能会陷入选择困境。传统的旅行规划方法往往依赖于人工操作&#xff0c;这不仅耗时耗力&#xff0c;而且难以保证计划的最优性和可执行性。 本…

Linux——/etc/passwd文件含义,grep,cut

/etc/passwd文件含义 作用 - 记录用户账户信息&#xff1a;共分为7段&#xff0c;使用冒号分割 含义 - 文件内容意义&#xff1a;账户名&#xff1a;密码代号x&#xff1a;UID&#xff1a;GID&#xff1a;注释&#xff1a;家目录&#xff1a;SHELL - 第7列/sbin/nologin&#x…

sheng的学习笔记-AI-聚类(Clustering)

ai目录 sheng的学习笔记-AI目录-CSDN博客 基础知识 什么是聚类 在“无监督学习”(unsupervised learning)中&#xff0c;训练样本的标记信息是未知的&#xff0c;目标是通过对无标记训练样本的学习来揭示数据的内在性质及规律&#xff0c;为进一步的数据分析提供基础。此类学…

WAIC2024 | 华院计算邀您共赴2024年世界人工智能大会,见证未来科技革新

在智能时代的浪潮汹涌澎湃之际&#xff0c;算法已成为推动社会进步的核心力量。作为中国认知智能技术的领军企业&#xff0c;华院计算在人工智能的广阔天地中&#xff0c;不断探索、创新&#xff0c;致力于将算法的潜力发挥到极致。在过去的时日里&#xff0c;华院计算不断探索…