刷题记录|Day46 ● 139.单词拆分 ● 多重背包理论

cpp中auto, auto &和const auto &的区别 笔者初学cpp,如有纰漏,请见谅并指正。 用在哪 auto用于推断类型,具体可用于声明变量时根据初始化表达式自动推断该变量的类型,也就是可用在for循环。 也可以用于声明函数返回值的占位符。 怎么用 这里主要讲for循环中三者的区别 直接说结论 auto auto用于copy一份集合中的数据,对于这种情况,在循环体中不论怎么修改copy的数据,是不会影响到原有集合中的数据的。 举个简单的例子 int arr[5] = {0, 1, 2, 3, 4}; cout << "使用auto" <& 阅读详情

● 139.单词拆分

题目描述

给你一个字符串 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

提示:

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

解题思路

  1. 确定dp数组以及下标的含义

dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词。

  1. 确定递推公式

如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。(j < i )。

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

  1. dp数组如何初始化

从递推公式中可以看出,dp[i] 的状态依靠 dp[j]是否为true,那么dp[0]就是递推的根基,dp[0]一定要为true,否则递推下去后面都都是false了。

那么dp[0]有没有意义呢?

dp[0]表示如果字符串为空的话,说明出现在字典里。

但题目中说了“给定一个非空字符串 s” 所以测试数据中不会出现i为0的情况,那么dp[0]初始为true完全就是为了推导公式。

下标非0的dp[i]初始化为false,只要没有被覆盖说明都是不可拆分为一个或多个在字典中出现的单词。

  1. 确定遍历顺序

题目中说是拆分为一个或多个在字典中出现的单词,所以这是完全背包。

还要讨论两层for循环的前后顺序。

如果求组合数就是外层for循环遍历物品,内层for遍历背包。

如果求排列数就是外层for遍历背包,内层for循环遍历物品。

我在这里做一个总结:

求组合数:动态规划:518.零钱兑换II (opens new window) 求排列数:动态规划:377. 组合总和 Ⅳ (opens new window)、动态规划:70. 爬楼梯进阶版(完全背包) (opens new window) 求最小数:动态规划:322. 零钱兑换 (opens new window)、动态规划:279.完全平方数 (opens new window)

而本题其实我们求的是排列数,为什么呢。 拿 s = “applepenapple”, wordDict = [“apple”, “pen”] 举例。

“apple”, “pen” 是物品,那么我们要求 物品的组合一定是 “apple” + “pen” + “apple” 才能组成 “applepenapple”。

“apple” + “apple” + “pen” 或者 “pen” + “apple” + “apple” 是不可以的,那么我们就是强调物品之间顺序。

所以说,本题一定是 先遍历 背包,再遍历物品。

  1. 举例推导dp[i]

以输入: s = “leetcode”, wordDict = [“leet”, “code”]为例,dp状态如图:
在这里插入图片描述

dp[s.size()]就是最终结果。

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        unordered_set<string> wordSet(wordDict.begin(), wordDict.end());
        vector<bool> dp(s.size()+1, false);
        dp[0] = true;
        for(int i = 0; i <= s.size(); ++i) {
            for (int j = 0; j < i; ++j) {
                string subword = s.substr(j, i - j);
                if(wordSet.find(subword) != wordSet.end() && dp[j] ){
                    dp[i] = true;
                }
            }
        }
        return dp[s.size()];
    }
};

运行结果

在这里插入图片描述

● 多重背包理论

有N种物品和一个容量为V 的背包。第i种物品最多有Mi件可用,每件耗费的空间是Ci ,价值是Wi 。求解将哪些物品装入背包可使这些物品的耗费的空间 总和不超过背包容量,且价值总和最大。

多重背包和01背包是非常像的, 为什么和01背包像呢?

每件物品最多有Mi件可用,把Mi件摊开,其实就是一个01背包问题了。

例如:

背包最大重量为10。

物品为:

重量价值数量
物品01152
物品13203
物品24302

问背包能背的物品最大价值是多少?

和如下情况有区别么?

重量价值数量
物品01151
物品01151
物品13201
物品13201
物品13201
物品24301
物品24301

毫无区别,这就转成了一个01背包问题了,且每个物品只用一次。

这种方式来实现多重背包的代码如下:

void test_multi_pack() {
    vector<int> weight = {1, 3, 4};
    vector<int> value = {15, 20, 30};
    vector<int> nums = {2, 3, 2};
    int bagWeight = 10;
    for (int i = 0; i < nums.size(); i++) {
        while (nums[i] > 1) { // nums[i]保留到1,把其他物品都展开
            weight.push_back(weight[i]);
            value.push_back(value[i]);
            nums[i]--;
        }
    }

    vector<int> dp(bagWeight + 1, 0);
    for(int i = 0; i < weight.size(); i++) { // 遍历物品
        for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
            dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
        }
        for (int j = 0; j <= bagWeight; j++) {
            cout << dp[j] << " ";
        }
        cout << endl;
    }
    cout << dp[bagWeight] << endl;

}
int main() {
    test_multi_pack();
}

机器学习【学校智慧食堂及其应用】 本文主要介绍机器学习【智慧食堂及其应用】 阅读详情

相关推荐

CLion与STM32CubeMX联调:JLink GDB Server高效调试指南

本文详细介绍了如何搭建并配置CLion、STM32CubeMX与JLink GDB Server联调的现代化STM32开发环境。通过一站式环境搭建、工程创建、核心调试配置及高级技巧(如RTT日志),该组合实现了高效的代码编辑、可视化配置与稳定调试,大幅提升嵌入式开发效率与体验。

web99的专栏 258

代码随想录算法训练营第day46|139.单词拆分 、多重背包

思路:可以重复多次使用字典里的单词,属于完全背包,字典里的单词相当于物品,给定的字符串相当于背包;将字典里的单词放到一个哈希表(集合)里,遍历的时候依次拆分给定字符串s,如果拆出单词能在字典里找到,则说明拆分成功,dp[i]=true;给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。当然还有那种二进制优化的方法,其实就是把每种物品的数量,打包成一个个独立的包。多重背包和01背包是非常像的, 为什么和01背包像呢?

qq_60513199的博客 1555

CMOS图像传感器系列--(四)HDR之LOFIC技术

CMOS图像传感器HDR技术之LOFIC解析 LOFIC(横向溢出积分电容器)技术是当前高动态范围成像的重要方案,通过在像素光电二极管旁设置高密度电容器收集溢出电荷,有效保留高光细节。该技术采用特殊像素结构,通过skim level触发电荷转移,实现单帧HDR成像。然而LOFIC存在显著局限性:高光区域噪声明显且难以消除,动态范围拓展不均衡(主要优化亮部),需复杂MIM工艺导致成本升高。为应对挑战,行业提出混合方案(如结合DCG技术)和工艺改进方向。OmniVision最新车载传感器OX08D10就采用了L

AIoT深度探索者 | 嵌入式系统架构师 深耕物联网(IoT)与人工智能(AI)融合技术,聚焦​​边缘计算、图像开发、低功耗通信协议​​,致力于智能硬件,关注我获取最新技术文章信息与海量资源~ 5795

【Day46】代码随想录值动态规划part8—单词拆分、多重背包理论、背包问题总结

【代码随想录之多重背包问题】多种背包跟01背包其实就是物品是否可以重复用的区别,然后多重背包还要组合与排列的问题,对应的就是遍历顺序的问题。多重背包在面试中基本不会出现,力扣上也没有对应的题目,大家对多重背包的掌握程度知道它是一种01背包,并能在01背包的基础上写出对应代码就可以了。背包问题是动态规划里面非常重要的一部分。常见的背包如下所示,主要以01背包和完全背包为主。其次记住动规五部曲:1、确定dp数组以及下标的含义;2、确定递推公式;3、dp数组如何初始化;4、确定遍历顺序;

格子格鸽的个人博客 895

Vivado FFT IP核配置与实战:FPGA信号处理硬件加速指南

快速傅里叶变换(FFT)是数字信号处理(DSP)中的核心算法,用于将时域信号转换到频域进行分析。其原理基于离散傅里叶变换(DFT),通过蝶形运算的分解与复用,大幅降低了计算复杂度。在工程实践中,软件实现的FFT难以满足高速实时处理的需求,因此硬件加速方案至关重要。FPGA凭借其并行架构和可定制性,成为实现高性能FFT的理想平台。通过集成专用的FFT IP核,如Vivado中的Pipelined Streaming I/O架构,可以构建流水线化的计算引擎,实现极低延迟和高吞吐量的连续数据流处理。这种硬件方案特

weixin_42536863的博客 646

BQ25798双电源输入4节电池升降压充电与最大功率跟踪于光伏板应用

介绍一颗具有窄范围直流电压NVDC、路径管理PPMT、光伏板最大功率跟踪及反向放电OTG升降压充电控制器,带I2C接口能对内部寄存器做控制

linkedin_38804946的博客 1676

代码随想录算法训练营Day46|139.单词拆分、多重背包理论基础、背包问题总结

这几天学的背包问题主要有三种:0-1背包、完全背包、多重背包。这三种背包问题的主要区别在于:0-1背包问题所有物品只有一件,每件物品至多只能存取一次;而完全背包问题所有物品都有无限件,可以对任意满足条件的背包取用任意次;多重背包问题每件物品都有一定的数量。对于背包问题,尤其要注意动规五部曲中第二步——确定递推公式和第四步——确定遍历顺序。

m0_68682181的博客 1226

告别双系统!用Ventoy把Ubuntu 22.04装进U盘,打造你的随身开发环境(附保姆级避坑指南)

本文详细介绍了如何使用Ventoy将Ubuntu 22.04安装到U盘,打造便携式开发环境。通过即插即用的特性,开发者可以在任何x86电脑上快速启动完整的Ubuntu系统,无需配置双系统或虚拟机。文章提供了从硬件准备到系统优化的全流程指南,帮助用户高效创建随身开发环境。

weixin_31569671的博客 364

代码随想录刷题day46| 单词拆分&&多重背包一刷跳过

单词拆分这一题,状态转移方程想不出来一点。。根本想不到。

东东唯一指定铲屎官 1103

用pyqtgraph 和pyqt5绘制股票K线图

# -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'QWidget_plot.ui' # # Created by: PyQt4 UI code generator 4.11.4 # # WARNING! All changes made in this file will be lost!...

qq_23114283的博客 5429

Java实现双色球&大乐透随机选号算法——原理详解与代码实战

掌握核心语法:集合操作、随机数生成、排序。贴近实际场景:将编程知识应用于生活问题的解决。

wangchl0932的博客 4974

Day46【动态规划】139.单词拆分、多重背包

背包问题完结!

yangjihua的个人笔记博客 896

动态时间规整(Dynamic Time Warping,DTW):让时间序列分析不再枯燥和代码全分析

动态时间规整(DTW)是一种用于比较时间序列相似性的算法,特别适用于处理长度不同或时间轴不对齐的序列。本文介绍了DTW的核心概念,包括其通过非线性对齐解决时间扭曲问题的能力,以及在语音识别、金融分析等领域的应用。通过Python代码示例,演示了如何计算两个模拟时间序列的DTW距离,并可视化最优对齐路径。结果显示,DTW能够有效捕捉序列间的相似模式,即使它们在时间轴上存在偏移或伸缩。该算法通过最小化累积距离来评估相似性,得分越低表明序列间相似度越高。

此星光明博客 162

Day 46 | 139.单词拆分 & 多重背包理论基础 & 背包问题总结

背包好难

m0_56579820的博客 502

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Day46 139.单词拆分 关于多重背包,你该了解这些!背包问题总结

确定dp数组(dp table)以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组。

233 846

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

刷题DAY46 | LeetCode 139-单词拆分 多重背包问题

现在有 N 种不同类型的矿石,每种矿石有一个重量 w[i],一个价值 v[i],以及最多 k[i] 个可用。对于多重背包,有N种物品和一个容量为V 的背包。求解将哪些物品装入背包可使这些物品的耗费的空间 总和不超过背包容量,且价值总和最大。在这个行星上,有许多不同类型的矿石资源,每种矿石都有不同的重要性和价值。如果物品数量很多的话,C++中,这种操作十分费时,主要消耗在vector的动态底层扩容上。输入共包括四行,第一行包含两个整数 C 和 N,分别表示宇航舱的容量和矿石的种类数量。背包最大重量为10。

wangs29的博客 907

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

代码随想录刷题Day46 | 139. 单词拆分 | 多重背包

代码随想录刷题Day46 | 139. 单词拆分 | 多重背包

DUM1615的博客 317

代码随想录刷题day46 139.单词拆分;多重背包;背包问题总结

代码随想录刷题day46

weixin_43127049的博客 309

代码随想录算法训练营DAY46|C++动态规划Part8|139.单词拆分、多重背包理论基础、背包问题总结篇

二刷后完成总结,这里先贴上卡哥的文章背包问题总结篇。

糖炒栗子 868

代码随想录Day46|139.单词拆分、关于多重背包,你该了解这些! 、背包问题总结篇!

139.单词拆分、关于多重背包,你该了解这些! 、背包问题总结篇!

weixin_46620779的博客 679

java算法day46 | 动态规划part08 ● 139.单词拆分 ● 关于多重背包,你该了解这些! ● 背包问题总结篇!

问能否能装满背包(或者最多装多少):对应题目如下:动态规划:416.分割等和子集动态规划:1049.最后一块石头的重量 II问装满背包有几种方法:dp[j] += dp[j - nums[i]] ,对应题目如下:动态规划:494.目标和动态规划:518. 零钱兑换 II动态规划:377.组合总和Ⅳ动态规划:70. 爬楼梯进阶版(完全背包)问背包装满最大价值:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

weixin_44802990的博客 829

【力扣一刷】代码随想录day46(动态规划part8 - 背包问题专题:139.单词拆分、多重背包基础、56. 携带矿石资源(第八期模拟笔试)、背包问题总结篇)

代码随想录-背包问题总结。

weixin_46135891的博客 920

代码随想录day46|139.单词拆分|多重背包简单介绍|背包总结|Golang

笔记

weixin_42161901的博客 410

DAY46 139.单词拆分 + 多重背包 + 背包问题总结篇

关于这几种常见的背包,其关系如下:通过这个图,可以很清晰分清这几种常见背包之间的关系。在讲解背包问题的时候,我们都是按照如下五部来逐步分析,相信大家也体会到,把这五部都搞透了,算是对动规来理解深入了。确定dp数组(dp table)以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组。

fuxxu的博客 205

算法训练营DAY46|139.单词拆分、多重背包的介绍

leetcode139.单词拆分、多重背包的介绍

weixin_59867637的博客 438

代码随想录算法训练营Day46 | 139.单词拆分 | 多重背包 | 背包问题总结

理论基础通过之前这一堆背包问题的练习,解决背包问题已经比较有套路了,对遍历顺序、初始化的理解也算不错。然而,将复杂的问题背景抽象成背包问题,仍然是需要经过思考的,其中最后一块石头的重量 II、目标和绝对是这种复杂抽象的难题。另外,很多背包问题看上去也都能用回溯算法解决,但毫无疑问都一定会超时。区别在于,背包问题依然能够依靠子问题的解来节省复杂度,而回溯算法不可避免地需要进行穷举,只不过是优雅的穷举,两者还是有本质上的区别。代码随想录上总结了不同的递推公式。

Kolbe_Huang的博客 419
上一篇: Linux--vi/vim的简单使用和常见命令
下一篇: 刷题记录|Day48 ● 198.打家劫舍 ● 213.打家劫舍II ● 337.打家劫舍III
null_one
博客等级 码龄8年 847粉丝 87原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值