代码随想录第46天|139.单词拆分,了解多重背包,背包总结

news2025/1/24 22:37:52

139.单词拆分

动规五部曲

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

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

2.valid初始化

valid[0]一定要为true,否则递推下去后面都都是false了

3.递推公式

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

4.遍历顺序

关于求组合还是排列还是最小数做一个总结:

求组合数:动态规划:518.零钱兑换II (opens new window)

求排列数:动态规划:377. 组合总和 Ⅳ (opens new window),动态规划:70. 爬楼梯进阶版(完全背包) (opens new window)

求最小数:动态规划:322. 零钱兑换 (opens new window)、动态规划:279.完全平方数

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

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

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

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

5.推导

代码实现

class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        //完全背包
        //valid[i]表示字符串下标为i时,可以被字符串列表中的字符拼接出来
        HashSet<String> set=new HashSet<>(wordDict);//,将字典 wordDict 转化为一个 HashSet 集合 set
        boolean[] valid=new boolean[s.length()+1];//valid[i] 表示从字符串 s 的第 0 个字符到第 i 个字符(不包括第 i 个字符)所组成的子串是否可以被字典中的单词拆分。
        valid[0]=true;
        for(int i=1;i<=s.length();i++){
            for(int j=0;j<i&&!valid[i];j++){
                if(set.contains(s.substring(j,i))&&valid[j]){//i表示截取的结束位置,j表示截取的起始位置
                    //对于每个子串,检查它是否存在字典中
                    valid[i]=true;//表示从0到i的子串可以被拆分
                }
            }
        }
        return valid[s.length()];//表示整个字符串s是否可以被拆分成字典中的单词

    }
}

多重背包

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

其实多重背包和01背包很想,01背包每个物品只有1个,多重背包只是每个物品有多个

ublic void testMultiPack1(){
    // 版本一:改变物品数量为01背包格式
    List<Integer> weight = new ArrayList<>(Arrays.asList(1, 3, 4));
    List<Integer> value = new ArrayList<>(Arrays.asList(15, 20, 30));
    List<Integer> nums = new ArrayList<>(Arrays.asList(2, 3, 2));
    int bagWeight = 10;

    for (int i = 0; i < nums.size(); i++) {
        while (nums.get(i) > 1) { // 把物品展开为i
            weight.add(weight.get(i));
            value.add(value.get(i));
            nums.set(i, nums.get(i) - 1);
        }
    }

    int[] dp = new int[bagWeight + 1];
    for(int i = 0; i < weight.size(); i++) { // 遍历物品
        for(int j = bagWeight; j >= weight.get(i); j--) { // 遍历背包容量
            dp[j] = Math.max(dp[j], dp[j - weight.get(i)] + value.get(i));
        }
        System.out.println(Arrays.toString(dp));
    }
}

背包问题总结

核心五步

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

01背包

01背包的一维和二维两种实现方式的差异体现在:

一维:倒序遍历(如果正序遍历背包的话一个物品会被放置多次),且必须先遍历物品再遍历背包(防止每个背包只放入一个物品)

二维:正序遍历,先遍历背包还是先遍历物品都可以

416. 分割等和子集:

01背包问题,先遍历物品再倒序遍历背包,要判断给定的数组能不能被分割成和相等的两组,首先对整个数组求和sum,然后得到target=sum/2,确定dp[i]表示容量为i背包的最大价值,确定递推公式为dp[j]=Math.max(dp[j],dp[j-nums[i]]+nums[i]);

1049. 最后一块石头的重量 II 

01背包问题,跟416 分割等和子集很像,先遍历物品再倒序遍历背包

494.目标和

01背包问题,先遍历物品再倒序遍历背包,首先公式推导得出left=(sum+target)/2,问题转换成在集合nums中找出和为left的组合。求装满背包有几种方法的情况下,递推公式一般为:dp[j]+=dp[j-nums[i]];

474.一和零

找出并返回 strs 的最大子集的长度,找出的该子集中最多有m个0和n个1,dp[i][j]表示i个0和j个1时的最大子集大小,首先要遍历字符串数组的每个字符串,统计每个字符串的0的个数和1的个数,然后倒序遍历zeroNum和倒序遍历oneNum

完全背包

完全背包相较于01背包就是物品可以取无限次

377. 组合总和 Ⅳ

这道题是排列问题不是组合,dp[i]: 凑成目标正整数为i的排列个数为dp[i],遍历顺序:target(背包)放在外循环,将nums(物品)放在内循环,内循环从前到后遍历,在遍历过程中需要判断容量j是否大于等于nums[i],只有满足这个条件才可以执行递推公式

518.零钱兑换II

求的是组合数,dp[i]表示凑成总金额为i的货币组合数,要判断coins[i]与我们当前遍历的背包的容量j的大小关系,现遍历背包还是先遍历物品都可以

有一个结论:求组合数先遍历物品再遍历背包;求排列数先遍历背包再遍历物品

70. 爬楼梯

之前没学背包问题前用普通动规分析就可以做,现在用完全背包的思路,dp[i]表示到达第i阶的方法数,要判断i与我们当前遍历的背包的容量j的大小关系,dp[j]+=dp[j-i];

322. 零钱兑换

dp[j]:凑足金额为j所需钱币的最少个数,这里也是求的组合问题。下标为0初始化为0,非0下标初始化为最大值,需要进行判断防止int类型溢出:

  if (dp[j - coins[i]] != Integer.MAX_VALUE) {

             //如果是dp[j - coins[i]等于Integer.MAX_VALUE,那么+1后溢出,变成-2147483648
                    dp[j]=Math.min(dp[j],dp[j-coins[i]]+1);

}

先遍历背包还是物品无所谓,求的是组合数的最小数,所以不影响,如果要求我们把所有组合情况列出来,那么我们就需要回溯法了

279.完全平方数

这道题和322. 零钱兑换思路基本一致,也是求组合数的最小数,dp[i]表示组成和为i的最少完全平方数个数,递推公式:dp[j]=Math.min(dp[j],dp[j-i*i]+1);先遍历背包还是物品无所谓

多重背包 

了解即可,因为多重背包问题可以被拆成01背包看

 

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

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

相关文章

TDesign WXS语法

目录 一、输出函数返回值如何获取&#xff1f; 二、WXS语法 三、WXS案例 一、输出函数返回值如何获取&#xff1f; 写在js的方法中 wxml中{{方法名()}}输出&#xff1a; 发现不显示&#xff1f;&#xff1f; 所以不能使用这种方式&#xff01;&#xff01; 二、WXS语法 1.…

idea启动缓慢解决办法

idea启动缓慢解决办法 文章目录 idea启动缓慢解决办法前言一、修改内存大小二、虚拟机运行大小三、插件禁用1、安卓相关2、构建工具3、Code Coverage 代码覆盖率4、数据库5、部署工具6、html和xml7、ide settings8、JavaScript框架和工具9、jvm框架10、Keymap快捷键映射11、kot…

c语言练习43:深入理解strcmp

深入理解strcmp strcmp的主要功能是用来比较两个字符串 模拟实现strcmp 比较两个字符串对应位置上的大小 按字典序进行比较 例如&#xff1a; 输入&#xff1a;abc abc 输出&#xff1a;0 输入&#xff1a;abc ab 输出&#xff1a;>0的数 输入&#xff1a;ab abc …

BUUCTF ciscn_2019_n_1 1

分析 使用file命令查看文件信息 使用IDA64打开文件 进入func函数 如果 v2 等于 11.28125 就可以拿到flag 可以看到v1有栈溢出&#xff0c;并且v1在v2的上面&#xff0c;可以通过溢出v2来覆盖v1的值从而获取flag 首先v1是浮点数 11.28125 的二进制是 0x413480 exp from…

【FPGA零基础学习之旅#13】串口发送模块设计与验证

&#x1f389;欢迎来到FPGA专栏~串口发送模块 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;FPGA学习之旅 文章作者技术和水平有限&#xff0c;如果文中出现错误&#xff0c;希望大家能指正&…

Redis 十大核心数据类型解析

一、Redis 简述 redis是一个开源的使用C语言编写的一个kv存储系统&#xff0c;是一个速度非常快的非关系远程内存数据库。它支持包括String、List、Set、Zset、hash五种数据结构。 除此之外&#xff0c;通过复制、持久化和客户端分片等特性&#xff0c;用户可以很方便地将red…

基于Yolov8的NEU-DET钢材表面缺陷检测,优化组合新颖程度较高:CVPR2023 PConv和BiLevelRoutingAttention,涨点明显

1.钢铁缺陷数据集介绍 NEU-DET钢材表面缺陷共有六大类,分别为:crazing,inclusion,patches,pitted_surface,rolled-in_scale,scratches 每个类别分布为: 2.基于yolov8的训练 原始网络如下: map@0.5为0.733

博客系统(升级(Spring))(三)登录功能,注册功能,注销功能

博客系统 (三&#xff09; 博客系统登录用户前端后端数据查询&#xff08;在mapper上添加mapper接口&#xff09; 注册用户前端后端插入数据 注销 博客系统 博客系统是干什么的&#xff1f; CSDN就是一个典型的博客系统。而我在这里就是通过模拟实现一个博客系统&#xff0c;这…

Spring Boot 中使用 Poi-tl 渲染数据并生成 Word 文档

本文 Demo 已收录到 demo-for-all-in-java 项目中&#xff0c;欢迎大家 star 支持&#xff01;后续将持续更新&#xff01; 前言 产品经理急冲冲地走了过来。「现在需要将按这些数据生成一个 Word 报告文档&#xff0c;你来安排下」 项目中有这么一个需求&#xff0c;需要将用户…

Linux平台如何实现采集音视频数据并注入轻量级RTSP服务?

技术背景 好多开发者&#xff0c;问我们最多的问题是&#xff0c;为什么要设计轻量级RTSP服务&#xff1f;轻量级RTSP服务&#xff0c;和RTSP服务有什么区别&#xff1f; 针对这个问题&#xff0c;我们的回答是&#xff1a;轻量级RTSP服务解决的核心痛点是避免用户或者开发者…

59、SpringBoot 自定义JSON的序列化器和反序列化器

Serialization(序列化)&#xff1a; 将java对象以一连串的字节码保存在磁盘文件中的过程&#xff0c;也可以说是保存java对象状态的过程。序列化可以将数据永久保存在磁盘上(通常保存在文件中)。 deserialization(反序列化)&#xff1a; 将保存在磁盘文件中的java字节码重新转…

关于µC/OS-III 多任务的基本理解

关于C/OS-III 多任务的基本理解 任务和任务管理是 RTOS 的核心&#xff0c;且大多数项目使用 RTOS 的目的就是为了使用 RTOS 的多任务管理能力。 C/OS-III作为经典的RTOS&#xff0c;了解并学习其任务管理机制&#xff0c;是非常有必要的。 文章目录 关于C/OS-III 多任务的基本…

进阶C语言-指针的进阶(中)

指针的进阶 &#x1f4d6;5.函数指针&#x1f4d6;6.函数指针数组&#x1f4d6;7.指向函数指针数组的指针&#x1f4d6;8.回调函数 &#x1f4d6;5.函数指针 数组指针 - 指向数组的指针 - 存放的是数组的地址 - &数组名就是数组的地址。 函数指针 - 指向函数的指针 - 存放的…

【Java】session的工作原理

文章目录 一、session的概念及特点session概念session主要有以下的这些特点 二、为什么要使用session三、session的工作原理四、session的生命周期Session何时生效Session何时失效 五、session的性能瓶颈六、session实现登录状态的控制 一、session的概念及特点 session概念 …

无涯教程-JavaScript - COUPDAYSNC函数

描述 COUPDAYSNC函数返回从结算日期到下一个息票日期的天数。 语法 COUPDAYSNC (settlement, maturity, frequency, [basis])争论 Argument描述Required/OptionalSettlement 证券的结算日期。 证券结算日期是指在发行日期之后将证券交易给买方的日期。 RequiredMaturity 证…

基于第二代 ChatGLM2-6B P-Tuning v2 微调训练医疗问答任务

今天是教师节&#xff0c;恭祝全体老师们节日快乐&#xff01;&#x1f60a; 一、ChatGLM2-6B 在本专栏前面文章中实验了使用 ChatYuan-large-v2 Freeze 微调训练医疗问答任务&#xff0c;训练后效果整体还可以&#xff0c;这篇文章继续探索使用最近比较火的 ChatGLM 官方推出…

docker镜像详解

目录 什么是docker镜像镜像相关命令docker pulldocker imagesdocker searchdocker rmi导出 / 导入镜像 镜像分层镜像摘要镜像摘要的作用分发散列值 什么是docker镜像 Docker镜像是Docker容器的基础组件&#xff0c;它包含了运行一个应用程序所需的一切&#xff0c;包括代码、运…

Sharding-Jdbc(2):Sharding-Jdbc入门案例

1 前置条件 搭建读写分离的数据库环境,搭建方法如下文,目标数据库test Mysql性能优化(5):主从同步原理与实现_mysql主从配置优化_不死鸟.亚历山大.狼崽子的博客-CSDN博客 2 新建maven项目 3 pom引入依赖 <?xml version="1.0" encoding="UTF-8"…

《protobuf》基础语法2

文章目录 枚举类型ANY 类型oneof 类型map 类型改进通讯录实例 枚举类型 protobuf里有枚举类型&#xff0c;定义如下 enum PhoneType {string home_addr 0;string work_addr 1; }同message一样&#xff0c;可分为 嵌套定义&#xff0c;文件内定义&#xff0c;文件外定义。不…

二维码智慧门牌管理系统:智能化地址管理,提升社会治理效率

文章目录 前言一、地址管理挑战二、二维码智慧门牌管理系统解决方案 前言 随着科技的飞速发展&#xff0c;我们的生活正经历前所未有的变革。尤其是智能化技术&#xff0c;已经深刻影响了我们的日常生活和工作环境。然而&#xff0c;在某些领域&#xff0c;如地址管理和社会治…