算法打卡day40|动态规划篇08| Leetcode 139.单词拆分|多重背包理论|背包问题总结篇

目录

算法题

 Leetcode  139.单词拆分

个人思路

解法

动态规划

回溯法

多重背包理论基础

背包问题总结篇

解题思路

背包递推公式

遍历顺序

01背包

完全背包


算法题

 Leetcode  139.单词拆分

题目链接:139.单词拆分

大佬视频讲解:单词拆分视频讲解

个人思路

这道题有点绕,思路没打开...

解法

这道题目的时候,可以使用回溯法解决,和之前做的一题很像分割回文串 ,是枚举分割后的所有子串,判断是否回文。而这里是判断是否在字典出现。除开回溯法,动态规划也能解决这道题。

动态规划

单词就是物品,字符串s就是背包,单词能否组成字符串s,就是问物品能不能把背包装满。拆分时可以重复使用字典中的单词,说明就是一个完全背包!

动规五部曲:

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

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

2.确定递推公式

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

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

3.dp数组如何初始化

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

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

4.确定遍历顺序

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

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

本题求的是排列数: 拿 s = "applepenapple", wordDict = ["apple", "pen"] 举例。

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

"apple" + "apple" + "pen" 或者 "pen" + "apple" + "apple" 是不可以的,所以强调物品之间顺序。

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

5.举例推导dp[i]

以输入: s = "leetcode", wordDict = ["leet", "code"]为例,dp状态如图:

class Solution {public boolean wordBreak(String s, List<String> wordDict) {HashSet<String> set = new HashSet<>(wordDict);boolean[] valid = new boolean[s.length() + 1];valid[0] = true;//初始化for (int i = 1; i <= s.length(); i++) {//遍历背包(字符串s)for (int j = 0; j < i && !valid[i]; j++) {//遍历物品if (set.contains(s.substring(j, i)) && valid[j]) {valid[i] = true;}}}return valid[s.length()];}
}

时间复杂度:O(n^2);(嵌套for循环)

空间复杂度:O( n);(存储一个长度为n+1的dp数组)

回溯法

class Solution {private Set<String> set;private int[] memo;public boolean wordBreak(String s, List<String> wordDict) {memo = new int[s.length()];set = new HashSet<>(wordDict);return backtracking(s, 0);}public boolean backtracking(String s, int startIndex) {// System.out.println(startIndex);if (startIndex == s.length()) {return true;}if (memo[startIndex] == -1) {return false;}for (int i = startIndex; i < s.length(); i++) {String sub = s.substring(startIndex, i + 1);// 拆分出来的单词无法匹配if (!set.contains(sub)) {continue;                }boolean res = backtracking(s, i + 1);if (res) return true;}// 这里是关键,找遍了startIndex~s.length()也没能完全匹配,标记从startIndex开始不能找到memo[startIndex] = -1;return false;}
}

时间复杂度:O(n);(其中n是字符串s的长度)

空间复杂度:O( n+m);(其中n是字符串s的长度,m是字典中词的数量)


多重背包理论基础

题目

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

多重背包和01背包是非常像的,因为这里的 每件物品最多有Mi件可用,把Mi件摊开,其实就是一个01背包问题了。

例如:

背包最大重量为10。

物品为:

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

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

和如下情况是一样的;这就转成了一个01背包问题了,且每个物品只用一次。

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

说明

多重背包相当于是一种01背包,用01背包的基础上写出对应代码就可以了。

解决代码

import java.util.Scanner;
class multi_pack{public static void main(String [] args) {Scanner sc = new Scanner(System.in);int bagWeight, n;//bagWeight背包容量 ;n:物品种类bagWeight = sc.nextInt();//获取用户输入数据,中间用空格隔开,回车键换行n = sc.nextInt();int[] weight = new int[n];int[] value = new int[n];int[] nums = new int[n];for (int i = 0; i < n; i++) weight[i] = sc.nextInt();for (int i = 0; i < n; i++) value[i] = sc.nextInt();for (int i = 0; i < n; i++) nums[i] = sc.nextInt();int[] dp = new int[bagWeight + 1];//初始化dp数组for (int i = 0; i < n; i++) { //先遍历物品再遍历背包,作为01背包处理for (int j = bagWeight; j >= weight[i]; j--) {//遍历每种物品的个数for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) {dp[j] = Math.max(dp[j], dp[j - k * weight[i]] + k * value[i]);}}}System.out.println(dp[bagWeight]);}
}

时间复杂度:O(n^2);(嵌套循环for 其中W是背包的最大容量)

空间复杂度:O( n);(dp数组大小)


背包问题总结篇

解题思路

卡哥的五部曲十分好用,以后都这样来逐步分析.

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

其实这五部里哪一步都很关键,但确定递推公式和确定遍历顺序都具有规律性和代表性

背包递推公式

问能否能装满背包(或者最多装多少):dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);

对应题目有:力扣:416.分割等和子集,1049.最后一块石头的重量 II

问装满背包有几种方法:dp[j] += dp[j - nums[i]]

对应题目有:力扣 494.目标和,518. 零钱兑换 II,377.组合总和Ⅳ

问背包装满最大价值:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

对应题目有:力扣 474.一和零​​​​​​​

问装满背包所有物品的最小个数:dp[j] = min(dp[j - coins[i]] + 1, dp[j]);

对应题目有:力扣  322.零钱兑换,279.完全平方数

​​​​​​​

遍历顺序

01背包

二维dp数组01背包先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历。

一维dp数组01背包只能先遍历物品再遍历背包容量,且第二层for循环是从大到小遍历(倒序)

完全背包

纯完全背包的一维dp数组实现,先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历。但是仅仅是纯完全背包的遍历顺序是这样的,题目稍有变化,两个for循环的先后顺序就不一样了。

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

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

相关力扣题目如下:

  • 求组合数:​​​​​​​518.零钱兑换II
  • 求排列数:​​​​​​​377. 组合总和 Ⅳ

如果求最小数,那么两层for循环的先后顺序就无所谓了,相关题目如下:

  • 求最小数:​​​​​​​322. 零钱兑换、​​​​​​​279.完全平方数

对于背包问题,其实递推公式算是容易的,难是难在遍历顺序上,如果把遍历顺序搞透,才算是真正理解了


 以上是个人的思考反思与总结,若只想根据系列题刷,参考卡哥的网址代码随想录算法官网

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

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

相关文章

Redis系列之基于Linux单机安装

Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库&#xff0c;并提供多种语言的 API。最近学习需要用到Redis&#xff0c;所以就去Linux服务器上部署一个&#xff0c;做下记录&#xff0c;方便…

【架构师】-- 浅淡架构的分类

什么是架构&#xff1f; 说到架构&#xff0c;这个概念没有很清晰的范围划分&#xff0c;也没有一个标准的定义&#xff0c;每个人的理解可能都不一样。 架构在百度百科中是这样定义的&#xff1a;架构&#xff0c;又名软件架构&#xff0c;是有关软件整体结构与组件的抽象描…

llama2.c与chinese-baby-llama2语言模型本地部署推理

文章目录 简介Github文档克隆源码英文模型编译运行中文模型&#xff08;280M&#xff09;main函数 简介 llama2.c是一个极简的Llama 2 LLM全栈工具&#xff0c;使用一个简单的 700 行 C 文件 ( run.c ) 对其进行推理。llama2.c涉及LLM微调、模型构建、推理端末部署&#xff08…

[计算机效率] 鼠标手势工具:WGestures(解放键盘的超级效率工具)

3.22 鼠标手势工具&#xff1a;WGestures 通过设置各种鼠标手势和操作进行绑定。当用户通过鼠标绘制出特定的鼠标手势后就会触发已经设置好的操作。有点像浏览器中的鼠标手势&#xff0c;通过鼠标手势操纵浏览器做一些特定的动作。这是一款强大的鼠标手势工具&#xff0c;可以…

机器学习(理论第一课)

一、理解人工智能、机器学习、深度学习、强化学习&#xff1f; 人工智能、机器学习和深度学习之间存在递进关系&#xff0c;它们的覆盖范围逐层递减。 **人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;**是最宽泛的概念&#xff0c;旨在研究、开发用于…

AWS服务器有哪些优势?

作为一家总部在美国的公司&#xff0c;AWS为什么会受到中国企业的喜爱&#xff1f;他有什么优势&#xff1f;九河云作为AWS合作伙伴&#xff0c;将会带读者展现使用AWS的优势。 首先是作为跨国企业&#xff0c;AWS在全球有数十个区域节点&#xff0c;这种广泛的地域覆盖不仅有…

神经网络解决回归问题(更新ing)

神经网络应用于回归问题 神经网络是处理回归问题的强大工具&#xff0c;它们能够学习输入数据和输出之间的复杂关系。 神经网络提供了一种灵活且强大的框架&#xff0c;用于建模和预测回归问题。通过 适当的 网络结构、训练策略和正则化技术&#xff0c;可以有效地从数据中学…

大模型笔记:Prompt tuning

1 NLP模型的几个阶段 1.1 第一阶段&#xff08;在深度学习出现之前&#xff09; 通常聚焦于特征工程&#xff08;feature engineering&#xff09;利用领域知识从数据中提取好的特征 1.2 第二阶段&#xff08;在深度学习出现之后&#xff09; 特征可以从数据中习得——>…

大数据相关组件安装及使用

自学大数据相关组件 持续更新中。。。 一、linux安装docker 1、更新yum sudo yum update2、卸载docker旧版本 sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine3、…

大话设计模式——18.策略模式(Strategy Pattern)

简介 是一系列算法的封装&#xff0c;即做的事情相同&#xff08;方法名称相同&#xff09;但是实现的方式不同&#xff0c;以相同方式调用所有的算法&#xff0c;减少算法与使用算法的耦合。直接调用方法。 UML图 应用场景 Java AWT中的LayoutManager&#xff08;布局管理器&…

ARCHE-2024第三届上海国际智慧档案展览会暨高峰论坛即将开幕

一、ARCHE-2024精彩即将开幕 为进一步推动档案行业新科技创新应用与档案信息化再上台阶&#xff0c;加强档案行业交流互动&#xff0c;强化档案行业创新意识&#xff0c;实现相互促进、共同发展&#xff0c;作为6.9国际档案日系列活动的重要延伸——“2024第三届上海国际智慧档…

echarts 如何设置(dataZoom)多个图形的数据区域一起联动缩放响应

数据区域联动缩放需要用到 dataZoom 的专属事件 dispatchAction 实现多个数据区域联动缩放功能 <div style"width:100%;height:320px;" id"test01"></div> <div style"width:100%;height:320px;" id"test02"></…

MAC(M1芯片)编译Java项目慢且发热严重问题解决方案

目录 一、背景二、排查三、解决四、效果以及结果展示五、总结 一、背景 使用idea编译项目等操作&#xff0c;经常性发热严重&#xff0c;并且时间慢。直到昨天编译一个项目用时30分钟&#xff0c;电脑温度很高&#xff0c;并且有烧灼的味道&#xff0c;于是有了此篇文章。 二、…

C++(六个默认成员函数)

目录 六个默认成员函数构造函数析构函数拷贝构造函数 总结 六个默认成员函数 默认成员函数的概念&#xff1a;如果用户不显式写&#xff0c;编译器会自动生成的函数&#xff0c;就是默认成员函数 构造函数 构造函数是六个默认成员函数之一&#xff0c;构造函数的功能类似于init…

懒人必备!4个PS抠图技巧,让你轻松处理复杂背景!

今天带给大家的又是一个绝对重要的知识&#xff0c;那就是“抠图”&#xff01; 在我们的设计中&#xff0c;抠图可以说是最常见的运用啦&#xff0c;简单的PS抠图我们都会&#xff0c;但是最令我们头痛的人物或者动物的毛发的抠图了&#xff0c;很多人都抠不好&#xff0c;我…

合并单元格的excel文件转换成json数据格式

github地址: https://github.com/CodeWang-Ay/DataProcess 类型1 需求1: 类似于数据格式: https://blog.csdn.net/qq_44072222/article/details/120884158 目标json格式 {"位置": 1, "名称": "nba球员", "国家": "美国"…

华为机试题

目录 第一章、HJ1计算字符串最后一个单词的长度&#xff0c;单词以空格隔开。1.1&#xff09;描述1.2&#xff09;解题第二章、算法题HJ2 计算某字符出现次数1.1&#xff09;题目描述1.2&#xff09;解题思路与答案第三章、算法题HJ3 明明的随机数1.1&#xff09;题目描述1.2&a…

eBPF专题一 | 手把手教你用eBPF诊断MySQL(含源码)

DBdoctor 是一款数据库内核级性能诊断工具&#xff0c;利用eBPF技术深入数据库内核&#xff0c;致力于解决数据库的一切性能问题。 被称之为“革命性”内核技术的eBPF一直以来都备受关注&#xff0c;而DBdoctor作为一款数据库性能诊断工具&#xff0c;首次将eBPF技术深入应用…

FPGA实现Canny算法(Verilog)

在边缘检测算法里面Sobel是比较简单的一个算法&#xff0c;但是其检测出来的边缘往往是比较粗的&#xff0c;效果不是很好&#xff0c;因为我们最理想的边缘肯定就是一个宽度为1的细线。 Canny算法在此基础上进行了改进&#xff0c;通过使用边缘的梯度信息进行非最大值抑制(NM…

【随笔】Git 高级篇 -- 最近标签距离查询 git describe(二十一)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…