【LeetCode动态规划#10】完全背包问题实战,其三(单词拆分,涉及集合处理字符串)

这篇具有很好参考价值的文章主要介绍了【LeetCode动态规划#10】完全背包问题实战,其三(单词拆分,涉及集合处理字符串)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

单词拆分

力扣题目链接(opens new window)

给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

说明:

拆分时可以重复使用字典中的单词。

你可以假设字典中没有重复的单词。

示例 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

思路

如果要往背包问题上靠的话,可以把wordDict中的单词视为"物品"把字符串s的长度视为背包容量(注意,这里说的是长度,即s.size)

思路听上去很常规,但是具体到实现方式上就有点复杂

五步走

1、确定dp数组含义

如果拿不准dp数组中的元素是什么类型,可以看看题目的示例返回的是什么类型的值,那一般就是需要找的值

这里题目要判定字典wordDict中的单词能不能拼成字符串s

那么实现过程中肯定要用字典wordDict中的单词与当前遍历区间内截取到的子串进行比较,要么相同要么不同,再结合示例的返回值,可以判断dp数组中的值应该是布尔类型

回到正题,dp数组究竟代表什么意思

假设有一个长度为i的字符串s的子串,若dp[i] = true

那么dp[i]表示该字符串可以拆分为1个或多个字典wordDict中的单词(可以理解为:dp[i]是对遍历过程中某个子串是否能拆分为wordDict中单词的一个认证,true就是能拆,false就是拆不了)

2+3、确定递推公式和初始化dp数组

这个递推公式的条件可太多了,为什么连起来一块说,看到后面就知道了

首先,因为我们要不断遍历字符串s并截取子串,通过查找子串是否存在于字典wordDict中来判断当前子串是否可以拆分

为什么要判断子串是否可以拆分?

因为一旦遍历完字符串s,那么此时的子串就是s本身了。进而就可以求s能不能被拆分为字典wordDict中的单词,这里体现了dp的思想,即前一轮遍历的子串会影响下一轮的,最终影响整个结果

所以,第一个条件是:所遍历区间内的子串必须出现在字典中

在说第二个条件之前,有必要说一下 "不断遍历字符串s并截取子串" 的实现方式

其实就是双指针

		for (int i = 1; i <= s.size(); i++) {   // 遍历背包
            for (int j = 0; j < i; j++) {       // 遍历物品
                string word = s.substr(j, i - j); //substr(起始位置,截取的个数)
                if (wordSet.find(word) != wordSet.end() && dp[j]) {//这里wordSet是一个unordered_set
                    dp[i] = true;
                }
            }
        }

下面用图来解释一下遍历过程

【LeetCode动态规划#10】完全背包问题实战,其三(单词拆分,涉及集合处理字符串)

上图推导了两层for循环的遍历过程,其中,外层for循环负责遍历字符串s(也就是所谓的背包),而内层for则用来在[j,i]区间内遍历所有该区域内的子串,用来在wordSet中查询

如图所示,当外层for遍历到 i = 4 ,才获取到第一个能在wordSet中查询到的子串"leet"

为什么不是在i = 3时得到? 因为substr函数截取子串的区间时左闭右开的,详见 题外话

注意j遍历截取区间[j,i]内所有子串的顺序:它是先截最长的(如图所示)

此时,如果我们将dp[0]初始化为true

那么,每次i移动的时候,j重置为0,dp[j]就为true

若本次i移动到的位置,在j第一次获取子串时就能获取到目标子串的话,其实就找到了一个满足条件的子串

所以,此时的dp[i]也应该为true

因此,第二个条件就是:[j, i] 这个区间的子串是否出现在字典里

综上所述,本题的递推公式是: if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。(j < i )

初始化就是dp[0] = true(我认为完全是为了代码实现考虑,没有别的含义),其余位置是false

4、确定遍历顺序

因为题目说了,字符串s中可能会有"一个或多个"能够拆分为字典中单词的子串,也就是说背包中可以放多个相同的物品(单词),所以这是一个完全背包问题

而构成子串必须按一定顺序才能构成字符串s,所以本题的完全背包求的是排序(排列有序组合无序)(排列组合的区别详见)

所以遍历顺序是:先背包容量后物品

代码

太绕了,终于到代码了文章来源地址https://www.toymoban.com/news/detail-419714.html

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        //定义dp数组
        vector<bool> dp(s.size() + 1, false);
        //初始化
        dp[0] = true;

        //遍历dp数组
        //先将wordDict放入一个unordered_set便于使用子串进行查找
        unordered_set<string> wordSet(wordDict.begin(), wordDict.end());

        for(int i = 1; i <= s.size(); ++i){//先遍历背包,字符串s
            for(int j = 0; j < i; ++j){//再遍历物品
                string word = s.substr(j, i - j);//使用j不断截取区间内的子串
                if(wordSet.find(word) != wordSet.end() && dp[j]) dp[i] = true;
            }
        }
        return dp[s.size()];
    }
};

到了这里,关于【LeetCode动态规划#10】完全背包问题实战,其三(单词拆分,涉及集合处理字符串)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 动态规划-背包问题-完全背包

    对比01背包,完全背包中的每件物品有无数件。 也就是说,每件物品可以拿0,1,…,k,…件。 dp[i][j]表示前i种物品,体积为j时的最大价值 对于第i件物品: 不拿:dp[i][j]⇐dp[i-1][j] 拿一件:dp[i][j]⇐dp[i-1][j-w[i]]+v[i] 拿两件:dp[i][j]⇐dp[i-1][j-2w[i]]+2v[i] … 拿k件:dp[i]][j]⇐dp[i

    2024年04月08日
    浏览(49)
  • 动态规划之背包问题——完全背包

    算法相关数据结构总结: 序号 数据结构 文章 1 动态规划 动态规划之背包问题——01背包 动态规划之背包问题——完全背包 动态规划之打家劫舍系列问题 动态规划之股票买卖系列问题 动态规划之子序列问题 算法(Java)——动态规划 2 数组 算法分析之数组问题 3 链表 算法

    2024年02月03日
    浏览(64)
  • 完全背包&多重背包问题(动态规划)

    完全背包问题: 每个物品使用次数没有限制,与0-1背包的不同之处在于 遍历背包的顺序 是正序。 多重背包问题: 与完全背包的区别在于,每一种物品是有个数限制的,不能无限选择。这篇博客讲解的非常详细,可以参考学习: 多重背包问题---超详细讲解+优化(不懂你揍我

    2024年04月10日
    浏览(48)
  • 【LeetCode动态规划#07】01背包问题一维写法(状态压缩)实战,其二(目标和、零一和)

    力扣题目链接(opens new window) 难度:中等 给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。 返回可以使最终数组和为目标数 S 的所有添加符号的方法数。 示例: 输入

    2023年04月18日
    浏览(63)
  • 【动态规划之完全背包问题】完全背包问题的通用解法与优化

    ⭐️ 前面的话 ⭐️ 本篇文章将介绍动态规划中的背包问题——完全背包问题,前面我们已经介绍了0-1背包问题,其实完全背包问题就只改了0-1背包问题的一个条件,即物品可选择次数由一次改为无数次,仅此而已,下面我们就来开始介绍完全背包问题。 📒博客主页:未见

    2023年04月22日
    浏览(50)
  • 动态规划——完全背包问题

    由于本人实力尚浅,接触算法没多久,写这篇blog仅仅是想要提升自己对算法的理解,如果各位读者发现什么错误,恳请指正,希望和大家一起进步。(●’◡’●) 了解完全背包问题前可以先去看看01背包问题(良心正解),先了解这个基础问题会更有利于你了解下面的完全背

    2024年02月04日
    浏览(49)
  • 动态规划:完全背包问题

    ACwing #3. 完全背包问题 完全背包问题和01背包问题很相似。 01背包问题每个物品只能选一个,而完全背包问题每个物品可以选无限次。 DP问题的关键是找到状态转移方程: ①定义f[i][j]表示从前 i 个物品中选择,体积为 j 的时候的最大价值。 ②那么转移方程f[i][j] = max(f[i - 1][j

    2023年04月19日
    浏览(46)
  • 算法系列--动态规划--背包问题(3)--完全背包介绍

    💕\\\"Su7\\\"💕 作者:Lvzi 文章主要内容:算法系列–动态规划–背包问题(3)–完全背包介绍 大家好,今天为大家带来的是 算法系列--动态规划--背包问题(3)--完全背包介绍 链接: 完全背包 可以发现完全背包问题和01背包问题还是特比相似的 分析: 完全背包问题 是 01背包问题 的推广

    2024年04月25日
    浏览(45)
  • 动态规划完全背包问题-java

    完全背包问题跟01背包问题思路大致一样,只不过对于物品的拿取次数不在限制,我们只需要考虑这点即可。 文章目录 前言 一、什么是完全背包问题? 二、问题模拟 1.样例数据 2.算法思路 三、代码如下 1.代码如下(示例): 2.读入数 3.代码运行结果 总结 完全背包问题跟

    2024年04月26日
    浏览(45)
  • 动态规划-----背包类问题(0-1背包与完全背包)详解

    目录 什么是背包问题? 动态规划问题的一般解决办法: 0-1背包问题: 0 - 1背包类问题  分割等和子集:  完全背包问题:  完全背包类问题 零钱兑换II: 背包问题(Knapsack problem)是一种组合优化的NP完全问题。 问题可以描述为:给定一组物品,每种物品都有自己的重量和价格

    2024年04月17日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包