代码随想录算法训练营第四十三天| LeetCode 1049.最后一块石头的重量II、494. 目标和、474.一和零

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

文章讲解/视频讲解:https://programmercarl.com/1049.%E6%9C%80%E5%90%8E%E4%B8%80%E5%9D%97%E7%9F%B3%E5%A4%B4%E7%9A%84%E9%87%8D%E9%87%8FII.html#%E6%80%9D%E8%B7%AF

状态:已解决

1.思路 

        其实这个题跟上个题416. 分割等和子集 - 力扣(LeetCode)很像,我们可以把整个石头分成两堆,为了使碰撞后剩余石头重量最小,那么就尽量使两堆石头的重量接近,怎么才能使两堆石头重量尽量接近呢?努力凑齐某堆石头接近sum/2即可。那么这道题就转换成了昨天的416题。具体分析看LeetCode 416.分割等和子集-CSDN博客。

        这题最后要求最小的石头重量,那么我们装sum/2的背包时,得到的价值(重量)dp[n]是 <= sum/2。故剩下的那堆石头价值(重量)>= dp[n],也就是sum-dp[n] >= dp[n]。故碰撞后剩余石头重量为 (sum-dp[n]) - dp[n]。

2.代码实现

class Solution {
public:int lastStoneWeightII(vector<int>& stones) {int sum = 0;for(int i=0;i<stones.size();i++){sum += stones[i];}int m = stones.size(),n = sum/2;vector<int> dp(n+1,0);vector<bool> flag(m,false);for(int i=0;i<m;i++){for(int j=n;j>=stones[i];j--){dp[j] = max(dp[j],dp[j-stones[i]]+stones[i]);}}return (sum-dp[n])-dp[n];}
};

二、494. 目标和

文章讲解/视频讲解:https://programmercarl.com/0494.%E7%9B%AE%E6%A0%87%E5%92%8C.html

状态:已解决

1.思路 

        这道题其实是有点难想的,最直接的思路就是回溯。那采用动规又该如何解决呢?我们注意看,我们向数组中的每个整数前添加 '+' 或 '-' ,然后串联起所有整数后,得到的实则为一堆数减去另一堆数的表达式。我们将所有的被减数作为一个整体,设为left,将所有的减数作为一个整体,设为right。由于此题的数组nums依旧是一开始都给定的,且要求每个数都要参与计算,那么left 和 right 的和就是固定的sum(nums中所有元素的和)。即:

left + right = sum;

left - right = target;

        解得:

 left = (sum + target)/2;

        由于 sum 和 target 都是样例给定的固定值,因此left也是固定值。故只需找到原数组有多少子集和为left,就可得到满足条件的表达式个数。那么此题就变成了一个背包问题:背包容量为left,物品数为nums.size(),重量为nums[i]。

(1)确定dp数组以及下标的含义:

        dp[j] 表示:填满j(包括j)这么大容积的包,有dp[j]种方法。

(2)确定递推公式:

        有哪些来源可以推出dp[j]呢?假如遍历到nums[i]时,那么凑成dp[j]就要看dp[j - nums[i]] 有多少种方法。因为nums有多个,那么每次遍历一个nums[i]都有一个对应相等的 j,故总的dp[j]就为所有j - nums[i] 的和。即dp[j] += dp[j - nums[i]]。

例如:dp[j],j 为5,

  • 已经有一个1(nums[i]) 的话,有 dp[4]种方法 凑成 容量为5的背包。
  • 已经有一个2(nums[i]) 的话,有 dp[3]种方法 凑成 容量为5的背包。
  • 已经有一个3(nums[i]) 的话,有 dp[2]中方法 凑成 容量为5的背包
  • 已经有一个4(nums[i]) 的话,有 dp[1]中方法 凑成 容量为5的背包
  • 已经有一个5 (nums[i])的话,有 dp[0]中方法 凑成 容量为5的背包

那么凑整dp[5]有多少方法呢,也就是把 所有的 dp[j - nums[i]] 累加起来。所以求组合类问题的公式,都是类似这种

(3)dp数组初始化:

        如果数组[0] ,target = 0,那么 bagSize = (target + sum) / 2 = 0。 dp[0]也应该是1, 也就是说给数组里的元素 0 前面无论放加法还是减法,都是 1 种方法。所以本题我们应该初始化 dp[0] 为 1。

(4)确定遍历顺序:

        在一维背包-CSDN博客中,我们讲过对于01背包问题一维dp的遍历,nums放在外循环,target在内循环,且内循环倒序。

(5)举例推导dp数组:

        输入:nums: [1, 1, 1, 1, 1], S: 3;bagSize = (S + sum) / 2 = (3 + 5) / 2 = 4

        dp数组状态变化如下:

2.代码实现 

class Solution {
public:int findTargetSumWays(vector<int>& nums, int target) {int sum = 0;for(int i=0;i<nums.size();i++){sum += nums[i];}int m = nums.size();int n = (sum + target)/2;vector<int> dp(m+1,0);if(abs(sum)<target) return 0;if((sum+target)%2==1) return 0;dp[0] = 1;for(int i=0;i<nums.size();i++){for(int j=n;j>=nums[i];j--){dp[j] += dp[j-nums[i]];}}return dp[n];}
};

时间复杂度:O(n × m),n为正数个数,m为背包容量

空间复杂度:O(m),m为背包容量

三、474.一和零

文章讲解/视频讲解:https://programmercarl.com/0474.%E4%B8%80%E5%92%8C%E9%9B%B6.html

状态:已解决

1.思路  

        这道题其实就是在01背包问题的基础上,将背包的维度上升了。也就是,决定背包容量的属性不仅只有重量一栏了,现有0的数量和1的数量两栏,二者共同决定了背包容量。那么这道题就转换成了一个背包问题:容量由m和n决定,物品有strs.size()个,每个物品的重量也是两个维度(0的个数和1的个数),每个物品的价值为1,现求该背包最多能装多少物品。

(1)确定dp数组以及下标:

dp[i][j]:最多有i个0和j个1的strs的最大子集的大小为dp[i][j]。

(2)确定递推公式:

跟一维类似,dp[i][j]由没添加strs[i]的左上角状态而来,即dp[i][j] = dp[i - zeroNum][j - oneNum] + 1(因为strs[i]加入了子集,故子集大小+1) 。由于可能部分集合strs[i] 0和1的个数相同,故dp[i][j]需要一直维护最大的dp[i - zeroNum][j - oneNum] + 1。

(3)dp数组的初始化:

跟前面的题没差,01背包的dp数组(滚动数组)初始化为0就可以。因为物品价值不会是负数,初始为0,保证递推的时候dp[i][j]不会被初始值覆盖。

(4) 确定遍历顺序:

还是跟前面的题一样,最外层物品正序,内层(两层)都是倒序。

(5) 举例推导dp数组:

以输入:["10","0001","111001","1","0"],m = 3,n = 3为例

最后dp数组的状态如下所示:

2.代码实现 

class Solution {
public:int findMaxForm(vector<string>& strs, int m, int n) {vector<vector<int>> dp(m+1,vector<int>(n+1,0));for(string str:strs){int zeroNum = 0,oneNum = 0;for(int i=0;i<str.size();i++){if(str[i] == '0') zeroNum++;else oneNum++;}for(int i = m;i >= zeroNum; i--){for(int j = n; j >= oneNum; j--){dp[i][j] = max(dp[i-zeroNum][j-oneNum]+1,dp[i][j]);}}}return dp[m][n];}
};

 时间复杂度: O(kmn),k 为strs的长度

空间复杂度: O(mn)

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

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

相关文章

ssm056基于Java语言校园快递代取系统的设计与实现+jsp

校园快递代取系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本校园快递代取系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短…

4核8G配置服务器多少钱?2024年阿里云服务器700元1年价格便宜

4核8G配置服务器多少钱&#xff1f;2024年阿里云服务器700元1年价格便宜。阿里云4核8G服务器租用优惠价格700元1年&#xff0c;配置为ECS通用算力型u1实例&#xff08;ecs.u1-c1m2.xlarge&#xff09;4核8G配置、1M到3M带宽可选、ESSD Entry系统盘20G到40G可选&#xff0c;CPU采…

Linux下的权限:论老流氓root的存在

文章目录 用户身份切换提权 权限管理文件访问者文件访问权限文件类型目录权限默认权限粘滞位 用户 Linux下有两中用户&#xff1a;超级用户&#xff08;root&#xff09;、普通用户 超级用户&#xff1a;可以在Linux系统下做任何事情&#xff0c;不受到限制普通用户&#xff…

Java PDF文件流传输过程中速度很慢,如何解决?

专栏集锦&#xff0c;大佬们可以收藏以备不时之需&#xff1a; Spring Cloud 专栏&#xff1a;http://t.csdnimg.cn/WDmJ9 Python 专栏&#xff1a;http://t.csdnimg.cn/hMwPR Redis 专栏&#xff1a;http://t.csdnimg.cn/Qq0Xc TensorFlow 专栏&#xff1a;http://t.csdni…

VulnHub系列 DC-4靶机 渗透详细过程 | 红队打靶

VulnHub系列 DC-4靶机详细渗透测试过程 目录 VulnHub系列 DC-4靶机详细渗透测试过程一、将靶机导入到虚拟机当中二、渗透流程主机发现端口扫描Web渗透暴力破解命令执行反弹shellSSH暴力破解提权 一、将靶机导入到虚拟机当中 靶机地址&#xff1a; https://download.vulnhub.c…

Matlab|基于改进遗传算法的配电网故障定位

目录 1 主要内容 2 部分代码 3 部分程序结果 4 下载链接 1 主要内容 该程序复现文章《基于改进遗传算法的配电网故障定位》&#xff0c;将改进的遗传算法应用于配电网故障定位中, 并引入分级处理思想, 利用配电网呈辐射状的特点, 首先把整个配电网划分为主干支路和若干独立…

中国12.5米DEM地形瓦片数据免费领取!

之前向大家公开了中国34个省12.5米DEM地形瓦片数据的免费领取链接&#xff0c;大家对12.5米DEM数据的使用需求很强烈&#xff0c;领取也很积极&#xff0c;也有不少读者反馈能否提供全国范围的12.5米DEM地形瓦片数据&#xff0c;因为分省级地形瓦片数据想要合并成全国数据&…

ES-全文搜索

模糊查询&#xff1a; 写数据通过id路由到master分片 查询数据到一个节点&#xff0c;该节点会作为一个调度节点判断负载等情况将请求转发到真正节点&#xff08;一般し轮询&#xff09;

提升批量邮箱API发送效率:技巧与策略探讨

批量邮箱API发送邮件时如何提高发送效率&#xff1f;1、优化邮件内容和目标客户列表&#xff1b;2、利用邮件模板和个性化功能&#xff1b;3、合理设置发送时间和频率&#xff1b;4、使用A/B测试和数据分析&#xff1b;5、保持邮件列表更新和清洁。 一、优化邮件内容和目标客户…

CMEF | 澳鹏Appen精彩亮相第89届中国国际医疗器械博览会

4月14日&#xff0c;为期四天的第89届中国国际医疗器械博览会&#xff08;CMEF&#xff09;盛大收官。如今&#xff0c;人们的健康需求在人口老龄化等一系列因素的影响下持续增长&#xff0c;这意味着卫生系统也面对着更多具有复杂健康需求的患者。信息化、数字化、智能化已经成…

双指针的引入和深入思考(持续更新中)

目录 1.引入双指针 2.使用场景 3.例题引入 1.引入双指针 当我们需要维护某个区间性质的或者是求满足某些性质的区间的长度时&#xff0c;对于一个区间是由左右端点的&#xff0c;我们有简单的枚举左右端点的O()的时间的做法&#xff0c;当时在大多数题目中是不可行的&#…

20240329-1-SVM面试题

SVM面试题 1. SVM直观解释 SVM&#xff0c;Support Vector Machine&#xff0c;它是一种二分类模型&#xff0c;其基本模型定义为特征空间上的间隔最大的线性分类器&#xff0c;间隔最大使它有别于感知机&#xff1b;其还包括核技巧&#xff0c;这使它成为实质上的非线性分类…

OpenCV从入门到精通实战(二)——文档OCR识别(tesseract)

导入环境 导入必要的库 numpy: 用于处理数值计算。 argparse: 用于处理命令行参数。 cv2: OpenCV库&#xff0c;用于图像处理。 import numpy as np import argparse import cv2设置命令行参数 ap argparse.ArgumentParser() ap.add_argument("-i", "--imag…

计算机中的小数表示

文章目录 前言整数表示的缺陷定点小数定点小数加法乘法运算 浮点数IEEE754浮点数标准移码阶码的移码表示 IEEE754中的特殊点两个0非规格化数字正常浮点数无穷大NaN 浮点数简单举例浮点数一些其余特性浮点数计算不符合结合律浮点数舍入规则浮点数与整数之间的相互转换 总结 前言…

记录一次k8s pod之间ip无法访问,问题排查与定位

记录一次k8s pod之间ip无法访问&#xff0c;问题排查与定位 问题展现现象 node之间通信正常 部分node上的pod无法通信 排查有问题node 使用启动网络测试工具 环境准备 docker 数据库mysql 使用有状态副本集合 --- apiVersion: apps/v1 kind: StatefulSet metadata:anno…

生成对抗网络GAN的扩展应用理解

注&#xff1a;本文仅个人学习理解&#xff0c;如需详细内容请看原论文&#xff01; 一、cycleGAN 1.整体架构&#xff1a; 将图片A通过生成器生成图片B&#xff0c;然后通过判别器判别图片B的真假&#xff1b;并且图片B通过另一个生成器生成A‘&#xff0c;让A和A’近似。 2…

C++ queue priority_queuestack 详解及模拟实现

1. stack的介绍和使用 1.1 stack的介绍 1. stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行元素的插入与提取操作。 2. stack是作为容器适配器被实现的&#xff0c;容器适配器即是对特定类封装作为其底层的容…

JVM垃圾回收与算法

1. 如何确定垃圾 1.1 引用计数法 在 Java 中&#xff0c;引用和对象是有关联的。如果要操作对象则必须用引用进行。因此&#xff0c;很显然一个简单 的办法是通过引用计数来判断一个对象是否可以回收。简单说&#xff0c;即一个对象如果没有任何与之关 联的引用&#xff0c;即…

Python pyglet制作彩色圆圈“连连看”游戏

原文链接&#xff1a; Python 一步一步教你用pyglet制作“彩色方块连连看”游戏(续)-CSDN博客文章浏览阅读1.6k次&#xff0c;点赞75次&#xff0c;收藏55次。上期讲到相同的色块连接&#xff0c;链接见&#xff1a; Python 一步一步教你用pyglet制作“彩色方块连连看”游戏-…

Ai2024安装包(亲测可用)

目录 一、软件简介 二、软件下载 一、软件简介 Adobe illustrator&#xff0c;常被称为“AI”&#xff0c;是一种应用于出版、多媒体和在线图像的工业标准矢量插画的软件。作为一款非常好的矢量图形处理工具&#xff0c;该软件主要应用于印刷出版、海报书籍排版、专业插画、多…