算法系列--动态规划--背包问题(2)--01背包拓展题目

💕"2024.3.28小米汽车发布"💕
作者:Lvzi
文章主要内容:算法系列–动态规划–背包问题(2)–01背包拓展题目
在这里插入图片描述

大家好,今天为大家带来的是算法系列--动态规划--背包问题(2)--01背包拓展题目

1.分割等和⼦集

链接:
https://leetcode.cn/problems/partition-equal-subset-sum/
在这里插入图片描述

分析:
本题属于01背包问题

从数组中选择一些数据,使其刚好符合某种带限制条件的和,就符合01背包问题的思路

01背包问题就是选择一些物品,实现不超过背包最大容量的最大价值

本题是选择一些数,判断能够实现最大和刚好等于sum/2的情况

还有一个是在分析状态转移方程时,最后一个位置选或者不选也可以用01问题

代码:

class Solution {public boolean canPartition(int[] nums) {int n = nums.length;int sum = 0;for(int x : nums) sum += x;// 求和if(sum % 2 == 1) return false;// 特判int N = sum / 2;// 创建dp表boolean[][] dp = new boolean[n + 1][N + 1];dp[0][0] = true;// 初始化for(int i = 1; i <= nums.length; i++) {for(int j = 1; j <= sum / 2; j++) {dp[i][j] = (dp[i - 1][j]) || (j - nums[i - 1] >= 0 && dp[i - 1][j - nums[i - 1]]);}}// 返回值return dp[nums.length][sum / 2];}
}

空间优化后的代码:

class Solution {public boolean canPartition(int[] nums) {int n = nums.length, sum = 0;for(int x : nums) sum += x;if(sum % 2 == 1) return false;int N = sum / 2;boolean[] dp = new boolean[N + 1];dp[0] = true;for(int i = 1; i <= n; i++) for(int j = sum / 2; j >= nums[i - 1]; j--) dp[j] = dp[j] || dp[j - nums[i - 1]];return dp[sum / 2];}
}

2.⽬标和

链接:
https://leetcode.cn/problems/target-sum/
在这里插入图片描述

分析:

题目要求是必须用到数组里面的所有数字进行拼接(可正可负),判断可以拼接为target的最大组合数

首先,因为要用到数组中所有的数字,所以可以先把数组总和sum求出,接着我们可以把sum拆分为两部分,一部分是拼接+的数字总和a,另一部分是拼接-的总和b(b是大于0的,这里仅仅只是数字的相加),则可以得出:

  • a + b == sum
  • a - b == target

将两式相加可得:
a == (sum + target) / 2

示意图:
在这里插入图片描述

那么本道题就可以转化为在数组中挑选若干个数,使其和等于a的最大组合数,这不就是01背包问题吗!,在一个集合内部挑选若干个物品,在满足某个限制的前提下,实现xxxx

说明:求出a之后还需要判断是否越界,主要有两种不符合条件的情况:

  1. a < 0,因为本题的target可以是负数,所以a可能是负数,但是数组中的数全是大于0的,根部无法凑出一个小于0的数
  2. (sum + target) / 2 != 0:当除不尽的时候就代表不存在这样的a,也就无法凑出target,返回0

接下来就是动态规划的思路:

  1. 状态表示:
    • dp[i][j] :nums在[1,i]区间数字,和为j的最大组合数
  2. 状态转移方程
    • 和经典的背包问题一样,也是根据最后一个位置选或不选来推导状态转移方程,要注意的是,本题求的是最大组合数,也就是dp[i][j]应该是两种情况的总和
      在这里插入图片描述
  3. 初始化
    • 初始化主要考虑第一行和第一列
    • 在这里插入图片描述
  4. 填表顺序
    • 从左往右,从上往下
  5. 返回值
    • dp[n][a]

代码:

class Solution {public int findTargetSumWays(int[] nums, int target) {int a = 0, sum = 0;for(int n : nums) sum += n;// 求和a = (target + sum) / 2;// 计算目标值if(a < 0 || (sum + target) % 2 == 1) return 0;// 创建dp表int n = nums.length;int[][] dp = new int[n + 1][a + 1];dp[0][0] = 1;// 填表for(int i = 1; i <= n; i++) {for(int j = 0; j <= a; j++) {dp[i][j] = dp[i - 1][j];if(j - nums[i - 1] >= 0)dp[i][j] += dp[i - 1][j - nums[i - 1]];}}return dp[n][a];}
}

空间优化后的代码

class Solution {public int findTargetSumWays(int[] nums, int target) {int a = 0, sum = 0;for(int n : nums) sum += n;// 求和a = (target + sum) / 2;// 计算目标值if(a < 0 || (sum + target) % 2 == 1) return 0;// 创建dp表int n = nums.length;int[] dp = new int[a + 1];dp[0] = 1;// 填表for(int i = 1; i <= n; i++)for(int j = a; j >= nums[i - 1]; j--)// 注意优化后的便利顺序dp[j] += dp[j - nums[i - 1]];return dp[a];}
}

第一行不初始化,放到填表之中,也是背包问题常用的一种优化手段

3.最后⼀块⽯头的重量II

链接:
https://leetcode.cn/problems/last-stone-weight-ii/description/
在这里插入图片描述

分析:
本题的难点就在于转化,光看数字无法得出什么有效的结论,我们将数字换为字母,看能得出什么结论:
在这里插入图片描述

最后发现整个问题的思路很像目标和那道题目(就在上面),但是目标和那道题目最终求的是一个具体数字,本题要求的是最后的值的绝对值尽可能的小,还是套用和目标和一样的分析思路,整个数组的和是sum,可以根据匹配的符号不同分为两部分a,b

假设a>b,则求得就是a-b的最小值,对于数组中的每一个数都是选或不选,这就是01背包问题的特征,可以使用01背包问题的思路解决

状态表示:

  • dp[i][j]:在[1,i]区间内,选取一定的数字,在不超过j的前提下,可以实现的最大和

状态转移方程和初始化都比较简单,这里不再赘述

返回值:

  • 最终返回的应该是a-b的最小值a = dp[n][sum/2],那么b = sum - a,所以最终应该返回sum - 2 * dp[n][sum/2]
    在这里插入图片描述
class Solution {public int lastStoneWeightII(int[] stones) {int n = stones.length, sum = 0;for(int x : stones) sum += x;int[][] dp = new int[n + 1][sum/2 + 1];// 创建dp表// 填表for(int i = 1; i <= n; i++) {for(int j = 0; j <= sum/2; j++) {dp[i][j] = dp[i - 1][j];if(j - stones[i - 1] >= 0)dp[i][j] = Math.max(dp[i][j],dp[i - 1][j - stones[i - 1]] + stones[i - 1]);}}return sum - 2 * dp[n][sum/2];// 返回(a-b)绝对值的最小值}
}

空间优化后的代码:

class Solution {public int lastStoneWeightII(int[] stones) {int n = stones.length, sum = 0;for(int x : stones) sum += x;int[] dp = new int[sum/2 + 1];// 创建dp表// 填表for(int i = 1; i <= n; i++)for(int j = sum/2; j >= stones[i-1]; j--) dp[j] = Math.max(dp[j],dp[j - stones[i - 1]] + stones[i - 1]);return sum - 2 * dp[sum/2];// 返回(a-b)绝对值的最小值}
}

以上就是算法系列--动态规划--背包问题(2)--01背包拓展题目全部内容,下一篇文章将会带来完全背包问题的介绍,敬请期待,我是LvZi

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

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

相关文章

史上最全-Java面试题(涵盖基础、高级、框架、微服务、中间件、大厂真题等28个大类超3000+面试题,全部附带详细答案)

3月4月又到了一年一度的跳槽黄金期,无论几年经验,也无论技术能力如何,跳槽前都离不开面试准备,其中刷面试题是重中之重。 刷面试题的时候一大痛点就是太分散了,需要自己根据知识点一项一项的去搜,容易遗漏知识点而且面试题质量无法保证,非常痛苦,基于此我花了两个月的…

微信小程序修改checkbox和radio的样式

我们在开发小程序的时候&#xff0c;有时候需要修改小程序中checkbox和radio的原生样式&#xff0c;如何修改呢&#xff1f;这里给大家提供了一份代码&#xff0c;大家可以试试。 首先是修改checkbox样式的代码&#xff1a; /* 重写 checkbox 样式 */ /* 未选中的 背景样式 *…

AMS概念以及面试相关整理

1、ActivityManagerService是什么&#xff1f;什么时候初始化的&#xff1f;有什么作用&#xff1f; ActivityManagerService&#xff08;AMS&#xff09;是什么&#xff1f; ActivityManagerService&#xff08;简称AMS&#xff09;是Android操作系统中的一个核心服务&#…

实现简易的 axios

1、实现逻辑 Promise XMLHttpRequest 封装 ① 返回一个 promise 实例 new XMLHttpRequest 并设置默认请求方式、请求根路径&#xff1b; 添加请求响应事件&#xff1b; 根据状态码&#xff0c;对应执行成功或者失败的调用函数&#xff0c;并把结果传进去&#xff1b; ② …

场内基金的折溢价

场内基金会出现折溢价&#xff0c;主要原因是场内基金有申购赎回&#xff0c;买入卖出这两套操作。 交易价格<基金净值&#xff0c;就是折价 交易价格>基金净值&#xff0c;就是溢价 如何判断场内基金的折溢价 ETF最好判断&#xff0c;有实时净值IOPV&#xff0c;交易价…

AOP切入点表达式基本格式

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 官方地址 https://docs.spring.io/spring-framework/reference/core/aop/ataspectj/pointcuts.html AOP切入点表达式基本格式如下&#xff1a; execution(modifiers-patte…

java针对:Sharing is only supported问题解决

#错误解决 当你运行出现报错&#xff1a;Java HotSpot™ 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended 问题翻译&#xff1a;Java HotSpot™ 64 位服务器 VM 警告&#xff1a;仅引导加载程序类…

OneDiff加速“图生生”,解锁电商AI图像处理新范式

2024年&#xff0c;电商领域正目睹生成式AI软件工具的飞速发展&#xff0c;AI Generated Content (AIGC) 技术在电商应用中的普及率正在显著提升&#xff0c;这类技术能够显著提高商业运营的效率&#xff0c;并促进业绩的稳步增长。 硅基流动研发的图片/视频生成推理引擎OneDif…

Linux:Jenkins:参数化版本回滚(6)

上几章我讲到了自动集成和部署 Linux&#xff1a;Jenkins全自动持续集成持续部署&#xff08;4&#xff09;-CSDN博客https://blog.csdn.net/w14768855/article/details/136977106 当我们觉得这个页面不行的时候&#xff0c;需要进行版本回滚&#xff0c;回滚方法我这里准备了…

电脑病毒详解(有bat版本 附代码)

众所周知&#xff0c;电脑病毒是所有用电脑的人最怕的东西。 它们是一种恶意软件&#xff0c;旨在破坏、感染或干扰计算机系统的正常运行。它们通过潜入计算机系统并在后台执行恶意代码来实现其目的。病毒可以通过互联网、可移动媒介&#xff08;如USB驱动器&#xff09;或下载…

Java基础知识总结(26)

MyBatis MyBatis框架解决的问题&#xff1a; 减轻使用JDBC的复杂性&#xff0c;不用编写重复的常见connection,Statement;不用编写关闭资源代码。直接使用java对象&#xff0c;表示结果数据。让开发者专注SQL的处理。其他分心的工作由MyBatis代劳。 三层架构 UI:&#xff0…

如何更好地收集软件需求并快速转换成软件功能

摘要 在软件开发过程中&#xff0c;需求收集与转换是确保项目成功的关键环节。本文详细探讨了如何更有效地收集软件需求&#xff0c;并迅速将这些需求转化为实际的软件功能&#xff0c;涉及的方法包括深入的用户研究、原型设计、敏捷开发方法以及持续的反馈循环。 关键词&…

【华为OD机试】机器人搬砖【C卷|100分】

题目描述 机器人搬砖,一共有N堆砖存放在N个不同的仓库中,第i堆砖中有bricks[i]块砖头, 要求在8小时内搬完。机器人每小时能搬砖的数量取决于有多少能量格, 机器人一个小时中只能在一个仓库中搬砖,机器人的能量格每小时补充一次且能量格只在这一个小时有效,为使得机器人损…

Hello算法2:复杂度分析

Hello算法2&#xff1a;复杂度分析 本文是基于k神的Hello 算法的读书笔记&#xff0c;请支持实体书。 https://www.hello-algo.com/chapter_paperbook/ 算法效率 算法效率评估 设计算法时&#xff0c;我们追求以下两个目标&#xff1a; 找出解法找出最优解 最优解通常包含…

Java 8中的Stream API及其用途详解

Java 8中的Stream API是Java函数式编程的一个核心组成部分&#xff0c;它允许你以声明性方式处理数据集合&#xff08;如列表、集合等&#xff09;。通过使用Stream API&#xff0c;你可以更方便地执行复杂的操作&#xff0c;如过滤、映射、排序和聚合&#xff0c;而无需编写大…

部署实施案例分析题

习题一 随着医院信息化程度的不断提高&#xff0c;各业务系统的全面上线&#xff0c;对IT基础架构的安全性、稳定性以及业务系统的连续性提出了较高的要求&#xff0c;运维工作也相同面临了前所未有的挑战。 为加强该医院的运维工作的规范化&#xff0c;并提高日常运维的工作…

实验7 内置对象response

编写代码&#xff0c;掌握request、response的用法。【参考课本4.6.2】 三、源代码以及执行结果截图&#xff1a; input.jsp <% page language"java" contentType"text/html; charsetutf-8" pageEncoding"utf-8"%> <!DOCTYPE html>…

LeetCode刷题笔记之动态规划(三)

一、子序列/子数组问题 子序列&#xff1a;按原数组的顺序排列&#xff0c;不一定是原数组中的相邻元素组成的。即子序列可以是不连续的。 子数组&#xff1a;原数组中连续的几个元素组成的数组。 1. 300【最长递增子序列】 题目&#xff1a; 给你一个整数数组 nums &#xff…

Redis面试题-缓存穿透,缓存击穿,缓存雪崩

1、穿透: 两边都不存在&#xff08;皇帝的新装&#xff09; &#xff08;黑名单&#xff09; &#xff08;布隆过滤器&#xff09; 解释&#xff1a;请求的数据既不在Redis中也不在数据库中&#xff0c;这时我们创建一个黑名单来存储该数据&#xff0c;下次再有类似的请求进来…

Q-Day提前?IBM警告:「量子+AI」将触发巨大风险!

Q-Day&#xff0c;即量子计算机强大到足以破解当前加密方案的时刻&#xff0c;原本被视为一个从近期到长期可能面临的挑战&#xff0c;而非刻不容缓的现实问题。然而&#xff0c;最新的研究发现似乎加速了这一天的到来。 IBM的研究团队在一篇论文中提出&#xff0c;混合量子经典…