代码随想录算法训练营Day38|1049. 最后一块石头的重量 II , 494. 目标和 , 474.一和零

好久不见,兄弟们,我终于把期末考试考完了,现在已经放暑假回家了,开始恶补算法了,那么废话不多说,来看今天的内容

1049. 最后一块石头的重量 II:代码随想录

这道题目的意思就是给你一个数组表示每个石头的重量,只要两个石头相撞,重量小的重量变为0,大的就要减去小的重量,为你撞到只剩最后一个石头的时候,他的最小的重量为多少,其实这题也是一样的,我们要尽可能的将所有的石头分成相同的重量的两堆,这样的话撞完之后,所剩下的重量就是最小的,所以这题首先就是先求出所有石头的重量的总和,然后定义一个target等于sum除以2,然后这个背包的容量就是target,我们要做的就是从这个数组中找到石头他们的重量加起来尽可能的等于target,下面直接来上动规五部曲

1.dp数组以及其下标的含义:

        dp[i]就是容量为i的背包所装的最大重量的物品,注意这里的价值就是物品的重量。

2.递推公式:

        dp[j] = max(dp[j],dp[j - nums[i]] + nums[i]);

3.dp数组初始化:

        当背包的容量为零时,所装的物品的最大价值为0,其余的都是由递推公式推导而来,由于要娶最大值,所以全部要初始化为0,一避免被覆盖

4.遍历顺序:

        由于这里我进行了状态压缩,使用的时滚动数组,所以外层循环遍历的时物品,内层循环遍历的时背包的容量,外层循环是从前往后,因为是由上一个状态推导而来,而遍历被背包的时候,你想想看,我这个当前遍历的值是由左上角和上方的值推导而来的,所以如果我也是从前往后遍历的话,那原来的值就会被覆盖,因为我这个是滚动数组,所以我这里就要从后往前遍历,为了避免值被覆盖

说完了这些,下面我们来看具体的代码的实现

class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        int sum=0;int n=stones.size();
        for(int i=0;i<n;i++) sum+=stones[i];
        int target=sum/2;
        vector<int> dp(1501,0);
        for(int i=0;i<n;i++){
            for(int j=target;j>=stones[i];j--){
                dp[j]=max(dp[j],dp[j-stones[i]]+stones[i]);
            }
        }
        return fabs(sum-2*dp[target]);
    }
};

注意在最后的时候,由于我这个/是向下取整的,所以我剩余的元素的和一定是大于等于这个dp[target] 的值的,所以我就直接返回他们两个的差值就可以了。来看下一题

494. 目标和:代码随想录

这道题目的意思就是给你一个整数数组nums还有一个数字target,他让你将一些数变成负数,然后让整个数组的元素的和等于target,问你有多少种方法,那么这样的一道题,我们怎么用背包问题来解决呢,这里我先假设一共有元素和为p的数是不加负号的,那也就是说有另外的sum-p的元素和是要加上负号的,那整个数组的元素和就是p-(sum-p)注意这里中间的代表的是加上负号的意思,实际上你也可以写成这样更方便理解,p + -(sum-p)=target,这样再转化一下就是2p=target+sum,也就是p=(target+sum)/2;这样我们是不是就将其转化为了一个背包问题了,就是从数组中取数,将容量为这么多的背包装满有多少种方法,明确了这一点,直接上动规五部曲

1.dp数组以及其下标的含义:

        dp[j] 表示的就是将容量为j的背包装满有多少种不同的方法

2.递推公式:

        这里我是要求一共有多少种方法,而不是像之前一样求最大的价值,所以这里我们来分析一下,你想想看,只要我们明确了nums[i],我们就可以确定有dp [ j - nums[i] ] 种方法,这里你可能有一点迷惑,我们再来看看dp数组的定义是什么,dp数组的定义是将背包容量为j的背包装满一共有多少种方法,那么这里我的j是此时背包的容量,那么nums[i]代表的就是当前元素的值,而j - nums[i]代表的就是装满这么多的背包一共有多少种方法,所以此时你懂了吗,但是这只是一种情况,因为外层循环的nums[i]是会不断地变化的,所以这里是要不断的累加的,故得出递推公式为:dp[j] += dp[j-nums[i]];

3.dp数组的初始化:

        这里你想想看当我的背包容量为0时,我的dp数组的值应该等于多少,有人觉得应该等于0,真的是等于0吗,这么说过去好像说得通,就是什么都不加就是0,但是我们初始化要看的是题目的意思,而不是自己想,假设nums={0} ,targe=0,这样dp数组的值还是0吗,很明显不是吧,所以我们的dp[0]应该要初始化为1

4.dp数组的遍历顺序:

        和前面的题目一样,外层循环从前往后,内层循环从后往前,因为值会被覆盖掉,因为这里进行了状态压缩,使用的是滚动数组

下面来看具体的代码的实现:

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        int sum=0;int n=nums.size();
        for(int i=0;i<n;i++) sum+=nums[i];
        sum+=target;
        if(sum<0 || sum%2!=0) return 0;
        vector<int> dp(10001,0);
        dp[0]=1;
        target=sum/2;
        //dp数组的含义:有dp[i]种方法装满容量为i的背包
        for(int i=0;i<n;i++){
            for(int j=target;j>=nums[i];j--){
                dp[j]+=dp[j-nums[i]];
            }
        }
        return dp[target];
    } 
};

注意这里如果一开始就不能整除的话,就可以直接返回0了,代表没有方法,这里再分享一下另一种做法

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

这里是利用dfs的方法递归调用的,我们就是只来看看dfs内部的部分,其他的都是差不多的,这里的i代表的就是数组的下标当i小于0时,代表已经没有物品可以选了,此时如果c也恰好为0,则代表找到了一种情况,就返回1,否则返回0,接着就是如果当前的元素都已经大于我的c了那肯定是不选,就直接让下标减一再返回并且这里c是不变的,因为没有选,如果不是的话,就是返回选与不选的和因为这里是求所有的情况,选或者是不选都有可能满足条件相加返回即可

接着在主函数中调用传入参数n-1,和target即可,这就是这道题目的解答

474.一和零: 代码随想录

这道题目的意思就是给你一个字符串数组nums,然后给你一个m和n分别表示子集中0和1的最大数量,让你找到一个子集,这个子集中最多有m个0和n个1,那么这样一个问题我们怎么用背包的思想来思考呢,其实这里只是将背包的容量提升到了两个维度,也就是1和0的数量,其他的都是不变的,明确了这一点我们直接来上动规五部曲

1.dp数组以及其下标的含义:

        这里注意我们虽然仍然是状态压缩,也就是用滚动数组,但是重点是我们这里重量是有两个维度的,也就是说明只用一个一维数组是不够的,所以这里我们要用一个二维数组来表示,i,j就是分别表示0的最大数量和1的最大数量,dp[i][j]就是代表一个子集的最大的长度,在1的个数最多为n和0的个数最多为m的情况之下

2.递推公式:

        这里对比以前的01背包,递推公式是一样的,只不过有两个维度需要考虑,这里的x,y分别表示当前遍历的字符串里的0个数和1的个数,也就是相当于之前的nums[i],所以递推公式就是dp[i][j]=max(dp[i][j] , dp[i - x][j - y] + 1) ,注意这里的价值就是子集的个数后面的加1代表选,选的话子集的个数必然要加1

3.dp数组初始化:

        这里当i,j为0时,必然都为0,所以全部初始化为0即可

4.遍历顺序:

        这里需要着重强调的是,即使我这里用的是二维数组,我任然是滚动数组,也就是最外层循环遍历的是数组里的字符串元素,内层遍历的是0和1两个维度,即使是两层循环在内部,任然是要从后往前遍历,因为如果是从前往后遍历会覆盖掉元素

来看具体的代码的实现:

class Solution {
public:
    int findMaxForm(vector<string>& nums, int m, int n) {
        vector<vector<int>> dp(m+1,vector<int>(n+1,0));
        for(string s:nums){
            int x=0;int y=0;
            for(char c:s){
                if(c=='0') x++;
                else y++;
            }
            for(int i=m;i>=x;i--){
                for(int j=n;j>=y;j--){
                    dp[i][j]=max(dp[i][j],dp[i-x][j-y]+1);
                }
            }
        }
        return dp[m][n];
    }
};

最后返回dp[i][j]即可,以上就是今天的全部内容了,继续努力吧!

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

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

相关文章

RoPE旋转位置编码从复数到欧拉公式

第二部分 从复数到欧拉公式 先复习下复数的一些关键概念 我们一般用表示复数&#xff0c;实数a叫做复数的实部&#xff0c;实数b叫做复数的虚部 复数的辐角是指复数在复平面上对应的向量和正向实数轴所成的有向角 的共轭复数定义为&#xff1a;&#xff0c;也可记作&#xff0…

鸿蒙开发:Universal Keystore Kit(密钥管理服务)【密钥使用介绍及通用流程】

密钥使用介绍及通用流程 为了实现对数据机密性、完整性等保护&#xff0c;可使用生成/导入的密钥&#xff0c;对数据进行密钥操作&#xff0c;比如&#xff1a; [加密解密][签名验签][密钥协商][密钥派生]开发前请熟悉鸿蒙开发指导文档&#xff1a;gitee.com/li-shizhen-skin…

前端面试题28(Vue3的Teleport功能在什么场景下特别有用?能给个例子吗?)

Vue 3 的 Teleport 功能在需要将组件的渲染结果放置在 DOM 树中与当前组件位置无关的任意位置时特别有用。这通常涉及到需要将某些UI元素&#xff08;如模态框、弹出菜单、通知、工具提示等&#xff09;从其逻辑上的父级组件中“提取”出来&#xff0c;放置到页面的更高层级或完…

OpenAI Gym Atari on Windows

题意&#xff1a;在Windows系统上使用OpenAI Gym的Atari环境 问题背景&#xff1a; Im having issues installing OpenAI Gym Atari environment on Windows 10. I have successfully installed and used OpenAI Gym already on the same system. It keeps tripping up when t…

2024已过半,还没试过在vue3中使用ioc容器吗?

Vue3 已经非常强大和灵活了&#xff0c;为什么还要引入 IOC 容器呢&#xff1f;IOC 容器离不开 Class&#xff0c;那么我们就从 Class 谈起 Class的应用场景 一提起 Class&#xff0c;大家一定会想到这是 Vue 官方不再推荐的代码范式。其实&#xff0c;更确切的说&#xff0c…

SSO单点登录-1-同浏览器进行单点登录

前端同域 客户端前端同域&#xff0c;则cookie可以存在相同的域名或顶级域名下&#xff0c;一个客户端登录成功后&#xff0c;将token信息保存到域名下的cookie中其他不同客户端访问时&#xff0c;因为域名或者顶级域名相同&#xff0c;也能取到域名下的cookie中的token信息并…

动态粒子发射特效404网站HTML源码

源码介绍 动态粒子发射404网站HTML源码&#xff0c;粒子内容可以进行修改&#xff0c;默认是4&#xff0c;0数字还有一个页面不存在英文&#xff0c;可以自行修改&#xff0c;喜欢的朋友可以拿去使用&#xff0c;源码是html&#xff0c;记事本打开修改即可&#xff0c;鼠标双击…

大模型应用元年,到底有哪些场景可以实际落地场景?

很多企业和个人都号称自己打造了AI大模型实际落地场景&#xff0c;其中有噱头、蹭热点&#xff0c;也有真实落地应用的。下面我将聊聊有哪些应用是真实落地可执行的。 大模型写作 生成式大语言大模型的看家本领非写作莫属。大模型输出logits的基础上加上top_p、top_k、temper…

昇思MindSpore学习笔记5-02生成式--RNN实现情感分类

摘要&#xff1a; 记录MindSpore AI框架使用RNN网络对自然语言进行情感分类的过程、步骤和方法。 包括环境准备、下载数据集、数据集加载和预处理、构建模型、模型训练、模型测试等。 一、概念 情感分类。 RNN网络模型 实现效果&#xff1a; 输入: This film is terrible 正…

Tomcat的负载均衡、动静分离

一、如何tomcat和nginx负载均衡及动静分离&#xff1a;2台tomcat&#xff0c;3台nginx来实现 1.首先设置tomcat1和tomcat2服务器 关闭两台tomcat的防火墙及安全机制&#xff1a;systemctl stop filwalld setenforce 0 进入tomcat目录的webapps中&#xff0c;创建test 2.配…

PI 接口日志设置

一、全局设置 SAP NetWeaver Administrator ---> 配置 ---> 基础架构 ---> Java系统属性 ---> 选择服务页签 ---> 选择 "XPI Adapter:XI"服务进行设置。 1760915 - FAQ: Staging and Logging in PI 7.3 and higher 2518441 - The tablespace PSAPSR…

亿康源精英盛宴暨亿康源启动成功举办

&#xff08;本台记者报&#xff09;2024年7月7日下午&#xff0c;亿康源精英盛宴暨启动仪式在杭州市中维歌德大酒店盛大举行。此次盛会不仅吸引了行业内的专业人才、著名投资界大咖和科技领域的杰出企业家&#xff0c;还汇聚了众多关注大健康产业的各界人士&#xff0c;共同见…

【Linux】进程间通信——匿名管道

为什么要进行进程间通信&#xff1f; 1.数据传输&#xff1a;一个进程需要将它的数据发送给另一个进程&#xff0c;比如我们有两个进程&#xff0c;一个负责获取数据&#xff0c;另一个负责处理数据&#xff0c;这时第一个进程就要将获取到的数据交给第二个进程 2.资源共享&…

永磁同步电机无速度算法--滑模观测器(反正切、反余弦)

一、原理介绍 在永磁同步电机滑模观测器控制中&#xff0c;转子的位置和转速信息与反动电势密切相关。滑模观测器控制基本设计思路是&#xff1a;利用永磁同步电机的电压、电流信息&#xff0c;通过永磁同步电机数学模型&#xff0c;估算出电机在两相静止坐标系中的反电动势信…

(十) Docker compose 本地部署 apollo

文章目录 1、apollo2、数据库准备3、启动后会用到的几个地址4、docker-compose运行 apollo方式一&#xff1a;使用容器 hostName 作为网络媒介apollo 客户端通过宿主机端口 拉取配置(推荐)apollo 客户端通过 自定义hostName 拉取配置 方式二&#xff1a;使用端口映射固定 ip 作…

transformer网络学习

Transformer encoder-decoder模型之间共享的是Encoder最后一层输出的hidden-state。 GitHub - huggingface/transformers: &#x1f917; Transformers: State-of-the-art Machine Learning for Pytorch, TensorFlow, and JAX. Bert2Bert中&#xff0c;Encoder的hidden-state同…

阿里开源语音理解和语音生成大模型FunAudioLLM

近年来&#xff0c;人工智能&#xff08;AI&#xff09;的进步极大地改变了人类与机器的互动方式&#xff0c;例如GPT-4o和Gemin-1.5等。这种转变在语音处理领域尤为明显&#xff0c;其中高精度的语音识别、情绪识别和语音生成等能力为更直观、更类人的交互铺平了道路。阿里开源…

JAVA Tesseract OCR引擎

Tess4j是一个基于Tesseract OCR引擎的Java库, Tesseract库最初由惠普实验室于1985年开发&#xff0c;后来被Google收购并于2006年开源。识别效果不好&#xff0c;速度还慢&#xff0c;但是好早好早了。 一、POM依赖 <!--OCR识别https://digi.bib.uni-mannheim.de/tesserac…

library source does not match the bytecode for class SpringApplication

library source does not match the bytecode for class SpringApplication 问题描述&#xff1a;springboot源码点进去然后download source后提示标题内容。spring版本5.2.8.RELEASE&#xff0c;springboot版本2.7.18 解决方法&#xff1a;把spring版本改为与boot版本对应的6.…

昇思25天学习打卡营第5天|MindSpore网络模型构建

打卡 目录 打卡 模型类 模型网络&#xff1a;定义与使用 模型层级分解 nn.Flatten 张量转换-演示查看 nn.Dense 全连接层-演示查看 nn.ReLU 非线性激活层-演示查看 nn.SequentialCell 有序网络容器 nn.Softmax 多分类概率预测 模型参数 前置感受&#xff1a;总的来说…