当前位置: 首页 > article >正文

LeetCode 算法:单词拆分 c++

  • 原题链接🔗:单词拆分
  • 难度:中等⭐️⭐️

题目

给你一个字符串 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 中的所有字符串 互不相同

动态规划

动态规划(Dynamic
Programming,简称DP)是一种在数学、管理科学、计算机科学和经济学中使用的,通过把原问题分解为相对简单的子问题的方式来求解复杂问题的方法。动态规划常常用于优化问题,特别是那些具有重叠子问题和最优子结构性质的问题。

动态规划的一般步骤包括:

  1. 问题定义:明确要解决的问题,并确定状态和决策。
  2. 递推关系(状态转移方程):找出问题的递推公式,即状态转移方程,它描述了问题的不同阶段之间的关系。
  3. 边界条件:确定初始状态或基本情况,为递推提供起点。
  4. 计算顺序:确定各状态按照什么顺序进行计算,以保证在计算当前状态时,所需要的子状态已被计算。
  5. 计算与存储:按照确定的顺序,逐个计算每个状态的值,并将其存储下来,以便在需要时使用。
  6. 构造解:根据计算得到的状态值,构造问题的解。

动态规划通常用于解决以下类型的问题:

  • 背包问题:包括0-1背包问题、完全背包问题和多重背包问题等。
  • 最长递增子序列:找出序列中最长的递增子序列。
  • 最短路径问题:如Dijkstra算法和Floyd算法。
  • 矩阵链乘问题:计算矩阵连乘的最优顺序。
  • 硬币找零问题:最少硬币找零问题。
  • 编辑距离问题:计算两个字符串之间的编辑距离。

动态规划的关键点在于识别问题的最优子结构和递归性质,以及如何将问题分解为更小的子问题。通过存储子问题的解,可以避免重复计算,从而提高算法的效率。

题解

  1. 解题思路:

LeetCode 上的 “单词拆分” 问题是一个经典的动态规划问题。题目要求是给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分成一个或多个在字典中出现的单词。例如:

  • 输入: s = “leetcode”, wordDict = [“leet”, “code”] 输出: true

  • 解释: 返回 true 因为 “leetcode” 可以被拆分成 “leet code”。

  • 解题思路:动态规划

    • 定义状态:dp[i] 表示字符串 s 从索引 0 到索引 i(包含索引 i)的部分是否可以完全由 wordDict 中的单词组成。

    • 状态转移方程:对于每个 i,我们需要检查所有可能的 j(j < i),看 s[j+1…i] 是否是 wordDict 中的一个单词。如果是,并且 dp[j] 为 true,那么 dp[i] 就可以设置为 true。

    • 初始化:dp[0] = true,因为空字符串总是可以被拆分。

      • 计算顺序:按照字符串 s 的索引从小到大的顺序计算 dp 数组。
    • 结果:dp[len(s)-1] 就是整个字符串 s 是否可以被拆分。

  1. c++ demo:
#include <iostream>
#include <string>
#include <vector>
#include <unordered_set>

class Solution {
public:
    bool wordBreak(std::string s, std::vector<std::string>& wordDict) {
        std::unordered_set<std::string> words(wordDict.begin(), wordDict.end());
        std::vector<bool> dp(s.length() + 1, false);
        dp[0] = true;

        for (int i = 1; i <= s.length(); ++i) {
            for (int j = 0; j < i; ++j) {
                if (dp[j] && words.find(s.substr(j, i - j)) != words.end()) {
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[s.length()];
    }
};

int main() {
    Solution solution;
    std::string s = "leetcode";
    std::vector<std::string> wordDict = { "leet", "code" };
    bool result = solution.wordBreak(s, wordDict);
    std::cout << (result ? "true" : "false") << std::endl;
    return 0;
}
  • 输出结果:

true

  1. 代码仓库地址:wordBreak

http://www.kler.cn/a/293732.html

相关文章:

  • 2024开发者浏览器必备扩展,不允许还有人不知道~
  • git commit 校验
  • 生成 Django 中文文档 PDF 版
  • 重新认识HTTPS
  • 人工智能的前沿研究方向与未来发展趋势
  • 详解kafka消息发送重试机制的案例
  • 栈和队列的数据结构
  • ASP.NET Core 入门教学八 集成RocketMQ消息队列
  • json字符串CSS格式化
  • 【python因果推断库12】工具变量回归与使用 pymc 验证工具变量5
  • DDoS对策是什么?详细解说DDoS攻击难以防御的理由和对策方法
  • Docker进入容器并运行命令
  • 【学习笔记】SSL证书安全机制之证书撤销
  • Docker 安装 MySQL 8.0 并支持远程访问
  • jmeter之循环控制器使用
  • 校园圈子论坛小程序如何搭建?校园多功能系统源码实现
  • 正点原子阿尔法ARM开发板-IMX6ULL(二)——介绍情况以及汇编
  • 基于飞腾平台的Hive的安装配置
  • 从贝叶斯角度理解卡尔曼滤波算法
  • 狂奔的荣耀,稳健的苹果:AI Agent手机竞速赛
  • Linux平台屏幕|摄像头采集并实现RTMP推送两种技术方案探究
  • 使用isolation: isolate声明隔离混合模式
  • 超声波测距模块HC-SR04(基于STM32F103C8T6HAL库)
  • 比较差异 图片 视频
  • 问题合集更更更之cssnano配置导致打包重新计算z-index
  • 中秋猜灯谜_猜字谜小程序源码,无需服务器