day43 动态规划part5

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

中等
提示
有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。

每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:

如果 x == y,那么两块石头都会被完全粉碎;
如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。
最后,最多只会剩下一块 石头。返回此石头 最小的可能重量 。如果没有石头剩下,就返回 0。

难点:本题其实就是尽量让石头分成重量相同的两堆,相撞之后剩下的石头最小,这样就化解成01背包问题了。很难想到这个点啊。其实就是分成尽量相同的两堆,互相碰撞,就能剩下最小了。其实就是设bagSize为sum/2,让其中一堆石头尽量接近bagSize。

class Solution {
    public int lastStoneWeightII(int[] stones) {
        int sum = 0;
        for (int i : stones) {
            sum += i;
        }
        int target = sum >> 1; // 右移1,不是2
        int dp[] = new int[target + 1]; // dp[j]表示容量为j时能获得的最大价值

        for (int i = 0; i < stones.length; i++) { // 遍历物品
            for (int j = dp.length - 1; j >= stones[i]; j--) {  // 遍历容量,注意这里的终止条件真的很精妙,二维的还需要if else判断一下,这里直接省略了
                dp[j] = Math.max(dp[j], dp[j - stones[i]] + stones[i]);
            }
        }
        int result = sum - 2 * dp[target];
        return result;
    }
}

494. 目标和

中等
给你一个非负整数数组 nums 和一个整数 target 。

向数组中的每个整数前添加 ‘+’ 或 ‘-’ ,然后串联起所有整数,可以构造一个 表达式 :

例如,nums = [2, 1] ,可以在 2 之前添加 ‘+’ ,在 1 之前添加 ‘-’ ,然后串联起来得到表达式 “+2-1” 。
返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

难点:

这道题目咋眼一看和动态规划背包啥的也没啥关系。
本题要如何使表达式结果为target,
既然为target,那么就一定有 left组合 - right组合 = target。
left + right = sum,而sum是固定的。right = sum - left
公式来了, left - (sum - left) = target 推导出 left = (target + sum)/2 。
target是固定的,sum是固定的,left就可以求出来。
此时问题就是在集合nums中找出和为left的组合。

网友思路:本质是选数字放在包包里过程

网友①

这里,我们可以把状态定义为dp【i】【j】,表示用数组中前i个元素组成和为j的方案数。那么状态转移方程就是:
dp【i】【j】 = dp【i-1】[j-nums【i】] + dp【i-1】[j+nums【i】]

这个方程的意思是,如果我们要用前i个元素组成和为j的方案数,那么有两种选择:第i个元素取正号或者取负号。如果取正号,那么前i-1个元素就要组成和为j-nums【i】的方案数;如果取负号,那么前i-1个元素就要组成和为j+nums【i】的方案数。所以两种选择的方案数相加就是dp【i】【j】。

但是这样定义状态会导致空间复杂度过高,因为我们需要一个二维数组来存储所有可能的状态。所以我们可以对问题进行一些变换,把它转化为一个背包问题。

我们可以把数组中所有取正号的元素看作一个集合P,所有取负号的元素看作一个集合N。那么有:

sum§ - sum(N) = target

sum§ + sum(N) = sum(nums)

两式相加得:

sum§ = (target + sum(nums)) / 2

也就是说,我们只需要找到有多少种方法可以从数组中选出若干个元素使得它们的和等于(target + sum(nums)) / 2即可。这就变成了一个经典的01背包问题。

所以我们可以把状态定义为dp【j】,表示用数组中若干个元素组成和为j的方案数。那么状态转移方程就是:

dp【j】 = dp【j】 + dp[j - nums【i】]

这个方程的意思是,如果我们要用若干个元素组成和为j的方案数,那么有两种选择:不选第i个元素或者选第i个元素。如果不选第i个元素,那么原来已经有多少种方案数就不变;如果选第i个元素,那么剩下要组成和为j - nums【i】 的方案数就等于dp[j - nums【i】]。所以两种选择相加就是dp【j】。

但是在实现这个状态转移方程时,有一个细节需要注意:由于每次更新dp【j】都依赖于之前计算过得dp值(也就是说当前行依赖于上一行),所以我们必须从后往前遍历更新dp值(也就是说从右往左更新),否则会覆盖掉之前需要用到得值。

最后返回dp【bag_size】即可。​

网友②:

这道题感觉没讲清楚呀。。建议不懂的同学自己先用二维数组来做,比较好理解,理解了之后再用一维数组。

  1. 含义:dp【i】【j】:从下标为【0…i】的物品里任取,填满j这么⼤容积的包,有dp【i】【j】种⽅法
    2. 递推式:dp【i】【j】 = dp【i-1】【j】 + dp【i-1】[j-nums【i】]
    dp【i-1】【j】是不将物品i放入背包的方式数,dp【i-1】[j-nums【i】]是将物品i放入背包的方式数
    3. 初始化:dp【0】【0】 = 1 表示装满容量为0的背包,有1种⽅法,就是装0件物品。
    如果nums【0】在范围内的话,dp【0】[nums【0】] = 1
    其他全为0
    4. 计算顺序:顺序,行优先​

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution {
    public int findTargetSumWays(int[] nums, int target) {
        int sum = 0;
        for (int num : nums) {
            sum += num;
        }
        if (Math.abs(target) > sum) return 0;
        if ((target + sum) % 2 == 1) return 0;
        int bagSize = (target + sum) / 2;   // x - (sum - x) = target
        int[] dp = new int[bagSize + 1]; // dp[j] 表示:填满j(包括j)这么大容积的包,有dp[j]种方法
        dp[0] = 1;
        for (int i = 0; i < nums.length; i++) { // 遍历物品(数字)
            for (int j = bagSize; j >= nums[i]; j--) { // 遍历背包
                dp[j] = dp[j] + dp[j - nums[i]];
            }
        }
        return dp[bagSize];
    }
}

总结:

在这里插入图片描述

474. 一和零

中等
给你一个二进制字符串数组 strs 和两个整数 m 和 n 。
请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。
如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。

分析:本题,物品就是strs里的字符串,背包容量就是题目描述中的m和n。

// 这个题建议先看看官方(或其他人)的三维数组的题解
class Solution {
    public int findMaxForm(String[] strs, int m, int n) {
        //dp[i][j]表示背包容量为i个0和j个1时的最大子集的数量
        int[][] dp = new int[m + 1][n + 1];
        int oneNum, zeroNum;
        
        for (String str : strs) {
            // 统计每个字符串里0 和 1的数量
            oneNum = 0;
            zeroNum = 0;
            for (char ch : str.toCharArray()) {
                if (ch == '0') {
                    zeroNum++;
                } else {
                    oneNum++;
                }
            }

            // 倒序遍历
            for (int i = m; i >= zeroNum; i--) {
                for (int j = n; j >= oneNum; j--) {
                    dp[i][j] = Math.max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);
                }
            }
        }

        return dp[m][n];
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

坚韧不拔,直至胜利的彼岸

当晨曦的第一缕光线透过夜幕的阴霾&#xff0c;希望与挑战并肩而来。在这个世界的每个角落&#xff0c;无数的个体都在经历着各自的斗争、失败、再斗争&#xff0c;直至最终的胜利。这是一个古老而永恒的循环&#xff0c;是成长的必经之路&#xff0c;它讲述着坚韧不拔的精神如…

【LeetCode】升级打怪之路 Day 26:回溯算法 — 集合划分问题

今日题目&#xff1a; 698. 划分为k个相等的子集 | LeetCode473. 火柴拼正方形 | LeetCode 参考文章&#xff1a; 经典回溯算法&#xff1a;集合划分问题 目录 LC 698. 划分为k个相等的子集 【classic&#xff0c;有难度】数据预处理&#xff1a;计算 target基本回溯优化 1&…

Zero-Change Object Transmission for Distributed Big Data Analytics——论文泛读

ATC 2022 Paper 问题 分布式大数据分析在很大程度上依赖于Java和Scala等高级语言的可靠性和多功能性。然而&#xff0c;这些高级语言也为数据传输制造了障碍。要在Java虚拟机&#xff08;JVM&#xff09;之间传输数据&#xff0c;发送方应将对象转换为字节数组&#xff08;序…

校验注解@Length提示Length.class 类文件具有错误的版本 55.0, 应为 52.0

你们好&#xff0c;我是金金金。 场景 我正在学习参数校验&#xff0c;启动项目时报错如下 实体类 依赖版本 报错信息 排查 看报错信息提示类文件具有错误的版本 55.0, 应为 52.0&#xff0c;猜测可能是版本的问题。 可以确实就是版本的关系了&#xff0c;8.0版本的只能在jd…

2024年基于springboot+vue的10个最新选题推荐

前言 &#x1f497;博主介绍&#xff1a;✌专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅&#x1f447;&#x1f3fb; 2024年Java精品实战案例《100套》 &#x1f345;文末获取源码联系&#x1f345; &#x1f31f…

VMware Fusion Pro 13:一站式虚拟化解决方案,满足多样化需求

VMware Fusion Pro 13是一款功能强大的虚拟机软件&#xff0c;专为Mac操作系统设计。它支持在Mac电脑上创建和管理多个虚拟计算机&#xff0c;允许用户在不同操作系统中进行软件测试、开发和部署&#xff0c;如Windows、Linux等。该软件采用了最新的虚拟化技术&#xff0c;能够…

逻辑 | 逻辑先修营

学习到更新日期逻辑先修营-3常见逻辑连词及逻辑表达2024-3-23 1.形式逻辑基础1 2.形式逻辑基础2 3.常见逻辑连词及逻辑表述 4.OR相关考点 5.AND相关考点 6.逻辑箭头基本考点1 7.逻辑箭头基本考点2 8.代入逻辑推理事实真1 9.代入逻辑推理事实真2 10.形式逻辑四大基本考点…

VUE3 Day12pinia

属性在解构时需要用到storeToRefs语法&#xff0c;而方法则不需要 官方文档&#xff1a;https://prazdevs.github.io/pinia-plugin-persistedstate/zh/ 如果不配将使用pinia的默认配置

用Kimichat学习王庆法老师关于Sora的文章

目录 一 引言:二 提示词方面:三 与Kimi的聊天记录我:假如你是一名大模型方面的专家,提取一下这篇文章的核心观点,用三列表格的形式,https://mp.weixin.qq.com/s/Y-vmxmPu4_-tHaeP35hDJg我:上述文章的一、Spacetime Latent Patches 潜变量时空碎片, 建构视觉语言系统部分…

设计模式及其在项目、框架中的应用

设计模式的作用&#xff1a; 1、类之间关系图&#xff0c;明确的角色及其关系、作用&#xff1b; 2、符合开闭原则&#xff0c;职责明确&#xff0c;并且开放的拓展点可以有效应对后期的变化。 &#xff08;一&#xff09;、责任链模式 适用场景&#xff1a; 在一个流程中&…

ArmSoM-Sige RK3588开发板产品简介

让我们在 5 分钟内了解 Sige7。 简介​ ArmSoM-Sige7采用Rockchip RK3588新一代旗舰级八核64位处理器&#xff0c;主频高达2.4GHz&#xff0c;6 TOPS算力NPU&#xff0c;最大可配32GB大内存。支持8K视频编解码&#xff0c;拥有丰富的接口&#xff0c;支持双2.5G网口、WiFi6 &…

Tomcat9.0.87闪退解决方案

运行Tomcat9.0.87闪退 报错&#xff1a;Neither the JAVA_HOME nor the JRE_HOME environment variable is defined At least one of these environment variable is needed to run this program 原因&#xff1a;使用了免安装的方法&#xff0c;直接运行bin目录下的startup.ba…

unity学习(68)——相机/模型的旋转/位置计算

这个比想象中要难&#xff0c;而且需要自己写。 1.相机可以转xy两个位置&#xff0c;可以点头和转圈。注意这里有一个if判断&#xff08;后面返回来发现了这些问题&#xff09; 2.角色不能点头&#xff0c;只能转圈。 难得是移动方向&#xff0c;因为移动方向(位置)和转向是相…

无人机三维建模过程中注意事项

无人机三维建模是指利用无人机技术进行三维建模&#xff0c;该方法通过无人机搭载的多种传感器&#xff0c;如摄像头、激光扫描仪等&#xff0c;获取建筑物的多角度影像数据&#xff0c;然后利用计算机视觉技术和三维重建算法&#xff0c;将这些影像数据转化为高精度的三维模型…

Redis基础命令集详解

目录 1.Redis基础命令 2.Redis的经典案例 2.1 缓存 2.2 计数器 2.3 发布订阅 Redis是一个开源、内存存储的数据结构服务器&#xff0c;它支持多种数据结构&#xff0c;如字符串、哈希表、列表、集合、有序集合等。在Redis中&#xff0c;使用一些基础的命令来操作这些数据结…

从零开始学习在VUE3中使用canvas(六):lineCap(线条端点样式)

一、简介 lineCap能够让我们设置线条的端点样式&#xff0c;例如 1. butt const ctx canvas.getContext("2d");ctx.lineCap "butt"; // 默认样式&#xff0c;也可以显式指定 2.round const ctx canvas.getContext("2d");//圆头ctx.lineCap …

BRAM底层原理详细解释(1)

目录 一、原语 二、端口简述 2.1 端口简介 2.2 SDP端口映射 三、端口信号含义补充说明 3.1 字节写使能&#xff08;Byte-Write Enable&#xff09;- WEA and WEBWE&#xff1a; 3.2 地址总线—ADDRARDADDR and ADDRBWRADDR 3.3 数据总线—DIADI, DIPADIP, DIBDI, and D…

SSL加密:保护数据传输的安全盾牌

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

是德科技keysight E5061B网络分析仪

181/2461/8938产品概述&#xff1a; Keysight(原Agilent) E5061B 是一款 ENA 系列网络分析仪&#xff0c;可以满足广泛的低频至高频电子元器件和电路测量需求。E5061B 现可提供新的 5 Hz 至 3 GHz 频域器件分析标准。 E5061B ENA系列网络分析仪从5Hz 至3GHz提供了广泛的频率范…

使用 ReclaiMe Pro 查找并恢复网络中的 SSH 服务器数据

天津鸿萌科贸发展有限公司是 ReclaiMe Pro 数据恢复软件的授权代理商。ReclaiMe Pro 数据恢复软件专注于恢复几乎所有文件系统及各种类型和复杂程度的 RAID 阵列。 在本文中&#xff0c;我们介绍 ReclaiMe Pro 对于采用 SSH 连接方式的网络服务器中数据的恢复方法。 ReclaiMe…