C++ day43 最后一块石头的重量 目标和 一和零

题目1:1049 最后一块石头的重量

题目链接:最后一块石头的重量

对题目的理解

整数数组stone[i]表示第i块石头的重量,每次从中选出任意两块石头(x<=y)粉碎

如果两块石头重量相等,就会被完全粉碎;如果不等,那么重量轻(x)的石头会被粉碎,另一块石头重量变为y-x

每次最多剩下一块石头,返回此石头可能的最小重量,如果没有石头剩下,就返回0

stone数组中的元素在1~100之间,数组长度在1~30之间

每次让数值相近的石头一起粉碎,这样最终得到的重量会减少,本题其实就是尽量让石头分成重量相同的两堆,相撞之后剩下的石头最小,这样就化解成01背包问题了

本题物品的重量是stones[i],物品的价值也是stones[i]

动规五部曲

1)dp数组的含义及下标i的含义

dp[j]:表示背包容量为j背的最大价值,

本题表示背包中容量是j时,最大重量是dp[j]

2)递推公式

01背包:dp[j]=max(dp[j],dp[j-weight[i]]+value[i])

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

3)dp数组初始化

dp[0]=0  ,根据递推公式,非零下标对应的dp[j]也初始化为0,这样才不会覆盖初始值

1 <= stones.length <= 30,1 <= stones[i] <= 100,所以最大重量就是30 * 100 ,但是背包只需要装最大重量的一半即可(因为将石头分成重量相等的两堆),target=sum/2=3000/2=1500

4)遍历顺序

先正序遍历物品,后倒序遍历背包

for(i=0;i<stones.size();i++){

      for(j=target;j>=stones[i];j--)}

5)打印dp数组

最后dp[target]里是容量为target的背包所能背的最大重量,那么分成两堆石头,一堆石头的总重量是dp[target],另一堆就是sum - dp[target],

因为target=sum/2,是直接抹去小数部分,所以sum-dp[target]>=target

最终石头的最小重量是result=(sum-dp[target])-dp[target]

代码

class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        //数组长度最大是30,数组中的元素最大是100,所以dp数组承受的最大重量是30*100=3000,分成重量相同的两堆,所以大小是1500+1
        //dp数组初始化
        vector<int> dp(1501,0);
        int sum = 0;
        for(int i=0;i<stones.size();i++){
            sum += stones[i];
        }
        int target = sum/2;
        //递推,先正序遍历物品,后倒序遍历背包
        for(int i=0;i<stones.size();i++){
            for(int j=target;j>=stones[i];j--){
            dp[j]=max(dp[j],dp[j-stones[i]]+stones[i]);
            }
        }
        int result = sum-dp[target]-dp[target];
        return result;

        
        

    }
};
  • 时间复杂度:O(m × n) , m是石头总重量(准确的说是总重量的一半),n为石头块数
  • 空间复杂度:O(m)

题目2:494 目标和

题目链接:目标和

对题目的理解

非负整数数组的每个数字前添加   '+'   或  '-' 得到表达式,计算表达式运算结果等于target的不同表达式的数目

本题还是分成两个部分,加法集合left    减法集合right,这两个集合满足下面的两个等式①②

①  left+right=sum

②  left-right=target

right=sum-left

left-(sum-left)=target-->2left-sum=taget   left=(target+sum)/2     注:只有能整除才能找到

如果不能整除,则不存在这样的元素组合使得运算结果等于target,

如果target的绝对值的大于sum,也是无解的

背包容量是left时,看元素中有多少种方式能够装满这个背包,每个元素只用1次,是01背包问题

动规五部曲

1)dp[j]数组即下标j的含义

背包容量为j时,装满背包有dp[j]种方法

2)递推公式   

递推公式:dp[j] += dp[j-nums[i]]      ,在后面在讲解背包解决排列组合问题的时候还会用到!

3)dp数组初始化

dp[0]=1,如果数组[0] ,target = 0,那么 left = (target + sum) / 2 = 0, dp[0]也应该是1, 也就是说给数组里的元素 0 前面无论放加法还是减法,都是 1 种方法。

根据递推公式 因为递推公式是累加的,dp[j]要保证是0的初始值,才能正确的由dp[j - nums[i]]推导出来。,所以非零下标的dp[j]初始为0

4)遍历顺序

01背包:正序遍历物品(元素),倒序遍历背包(left)

5)打印dp数组

代码

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 left = (target+sum)/2;//dp数组里面尽可能地装left容量   -500~1000
        if((target+sum)%2==1) return 0;
        if(abs(target)>sum) return 0;
        //初始化dp数组
        vector<int> dp(left+1,0);
        dp[0]=1;
        //递推
        for(int i=0;i<nums.size();i++){
            for(int j=left;j>=nums[i];j--){
                dp[j] += dp[j-nums[i]];
            }
        }
        return dp[left];
    }
};
  • 时间复杂度:O(n × m),n为正数个数,m为背包容量
  • 空间复杂度:O(m),m为背包容量

本题记住:装满背包有几种方法,递推公式为

dp[j] += dp[j-nums[i]];

题目3:474一和零

题目链接:一和零

对题目的理解

返回二进制字符串数组strs最大子集长度,该子集中最多有m个0和n个1,二进制字符串仅由0,1组成

题目要求:strs字符串数组中至少有1个字符串,最多有600个字符串;每个字符串的长度至少为1,最多是100

背包有两个维度,m个0和n个1,装满这个背包有多少个物品

不同长度的字符串就是不同大小的待装物品,每个物品只能使用1次,所以是01背包问题

动规五部曲

1)dp数组及下标i的含义

二维dp数组,dp[i][j]  装满i个0,j个1的背包最多背了dp[i][j]个物品

2)递推公式

01背包递推公式:dp[j]=max(dp[j],dp[j-weight[i]]+value[i])

每个物品的重量是x个0,y个1,是两个维度,所以递推公式为dp[i][j]=max(dp[i][j], dp[i-x][j-y]+1)

3)dp数组初始化

dp[0][0]=0   非零下标 ,若初始化为一个较大的正整数,那么根据递推公式,值会被覆盖掉

所以非零下标的dp[j]也初始化为非负整数的最小值,即0

4)遍历顺序

01背包:先正序遍历物品strs里的字符串,后倒序遍历背包(两个维度,m和n)

5)打印dp数组

代码

class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
        //定义并初始化dp数组,这个数组是一个二维数组,有这两个重量0和1
        vector<vector<int>> dp(m+1,vector<int>(n+1,0));
        //递推,先正序遍历物品,后倒序遍历背包
        for(string str:strs){
            //遍历物品(字符串数组)
            int x=0;//记录当前字符串中0的个数
            int y=0;//记录当前字符串中1的个数
            for(char c:str){//遍历字符串中的每个字符,统计字符串中0和1的数量
                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];
    }
};
  • 时间复杂度: O(kmn),k 为strs的长度
  • 空间复杂度: O(mn)

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

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

相关文章

Docker Swarm总结+Jenkins安装配置与集成snarqube和目标服务器(4/5)

博主介绍&#xff1a;Java领域优质创作者,博客之星城市赛道TOP20、专注于前端流行技术框架、Java后端技术领域、项目实战运维以及GIS地理信息领域。 &#x1f345;文末获取源码下载地址&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb;…

分析某款go端口扫描器之一

一、概述 进来在学go的端口检测部分&#xff0c;但是自己写遇到很多问题&#xff0c;又不知道从何入手&#xff0c;故找来网上佬们写的现成工具&#xff0c;学习一波怎么实现的。分析过程杂乱&#xff0c;没啥思路&#xff0c;勿喷。 项目来源&#xff1a;https://github.com/…

python 基于opencv和face_recognition的人脸识别

python 基于opencv和face_recognition的人脸识别 代码如下&#xff1a; 使用一个photos存放你需要识别的照片&#xff0c;注意一个人一张就行 然后通过下面代码注册用户&#xff0c;之后启动程序&#xff0c;就会调用摄像头进行识别了。 AddPhoto(“发哥”, “./photos/fag…

【yolov5人行道-斑马线目标检测】

yolov5人行道-斑马线目标检测 数据集yolov5人行道-斑马线目标检测检测模型 数据集 YOLOv5是一种目标检测算法&#xff0c;可以用于检测图像中的人行道-斑马线。在目标检测领域&#xff0c;YOLOv5通过结合多种技术手段&#xff0c;包括使用Mosaic数据增强操作、自适应锚框计算与…

TIME_WAIT状态TCP连接导致套接字无法重用实验

理论相关知识可以看一下《TIME_WAIT相关知识》。 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<arpa/inet.h> #include<sys/socket.h> #include<errno.h> #include<syslog.h> #inc…

【ArcGIS Pro二次开发】(78):批量合并GDB数据库

有些GDB数据库会按分幅或行政区划进行分开储存&#xff0c;尤其是一些地形测绘或国情地理数据。 如下图所示&#xff1a; 数据是完整的&#xff0c;但使用的时候要一个一个拖进地图中&#xff0c;进行分析的时候也需要将其合并后使用。 因此就做了这个合库工具。 一、要实现的…

直播前期准备

直播前的准备是一个综合性的过程&#xff0c;需要从多个方面进行考虑和准备。以下是一些直播前准备的参考∶ 1.确定直播主题和目标∶明确直播的主题和目标&#xff0c;以及如何吸引观众。考虑观众的兴趣和需求&#xff0c;选择一个熟悉且具有吸引力的主题&#xff0c;以提升直…

字符串相似度匹配算法_莱茵斯坦距离算法

package day0330;public class LevenshteinDistanceUtil {public static void main(String[] args) {String a "WN64 F98";String b "WN64 F98 ";System.out.println("相似度:" getSimilarityRatio(a, b));}/*** 获取两字符串的相似度* * par…

扫码听音乐该如何制作?音乐的二维码生成方法

多个音频文件怎么做成一个二维码显示&#xff1f;二维码在现在的生活中拥有丰富的使用场景&#xff0c;可以用来作为多种内容类型的载体&#xff0c;比如音频二维码就是经常被使用的一种二维码类型。通过扫秒二维码来听音频文件&#xff0c;更加的灵活方便&#xff0c;那么音频…

六、shell编程

详见 《shell编程超详细入门教程》

队列基础(循环队列)

1.队列的定义: 和栈相反,队列(queue)是一种先进先出(first in first out,缩写为FIFO)的线性表.它只允许在表的一端进行插入,而在另一端删除元素. 在队列中,允许插入的一端叫做队尾(rear),允许删除的一端则称为队头(front). 2.循环队列的设计图示: 3.循环队列的结构设计: ty…

电话销售如何提高成功率

电话销售是一种非常有效的销售方式&#xff0c;睡着通信技术&#xff0c;互联网的发展&#xff0c;现在电话销售已经成为一种重要的销售方式&#xff0c;很多行业和领域都有使用。 虽然最终目的都是为了将产品卖出去&#xff0c;但是对于电话销售来说&#xff0c;前期寻找客户…

MySQL进阶知识:锁

目录 前言 全局锁 表级锁 表锁 元数据锁&#xff08;MDL&#xff09; 意向锁 行级锁 行锁 行锁演示 间隙锁/临界锁 演示 前言 MySQL中的锁&#xff0c;按照锁的粒度分&#xff0c;分为以下三类 全局锁&#xff1a;锁定数据库中的所有表。表级锁&#xff1a;每次操…

11-@Transaction与AOP冲突解决

如题&#xff0c;最近碰到了一个问题&#xff0c;在public方法上添加Transaction没有生效&#xff0c;事务没有回滚。 我自己模拟了一个功能&#xff0c;向数据库表User里面插入用户数据。说一下代码背景&#xff0c; 数据库MySQL&#xff0c;持久化层Mybatis&#xff0c;项目使…

Linux系统编程 day07 信号

Linux系统编程 day07 信号 1. 信号的介绍以及信号的机制2. 信号相关函数2.1 signal2.2 kill2.3 abort和raise2.4 alarm2.5 setitimer 3. 信号集4. 信号捕捉函数6. SIGCHLD信号7. SIGUSR1与SIGUSR2 1. 信号的介绍以及信号的机制 信号是信息的载体&#xff0c;在Linux/Unix环境下…

行业追踪,2023-11-30

自动复盘 2023-11-30 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…

企业数字化转型应对传统网络挑战的关键策略

数字化变革正在以前所未有的速度和规模改变着我们的生活和工作方式&#xff0c;使得传统网络架构面临着巨大的挑战。其中包括带宽需求增加、多云应用增加、安全威胁增加以及传统网络设备无法满足需求等问题。 数字化时代需要更高速、更可靠、更安全的网络支持&#xff0c;传统网…

C语言必备知识--函数返回局部变量

0.总结 1. 不能以局部变量的方式创建字符串数组的首地址 2.如果函数的返回值非要是一个局部变量的地址&#xff0c;那么该局部变量一定要申明为static类型 3.返回指向字符串常量的指针 4.数组不能作为函数返回值 5.在函数中可以返回局部变量的值&#xff0c;但是不能返回…

如何安装鸿蒙Harmony 4.0低版API9三方库

比如我要用下拉刷新三方库pulltorefresh 安装命令如下 ohpm install ohos/pulltorefresh 安装完后然后运行Demo报错,说没有isAtEnd方法 然后查看pulltorefresh 最新版2.0.4对应Harmony API10,然而我的手机是API9,所以必须找到API9的库&#xff0c;然后查看2.0.1是还是API9 所…

docker集群的详解以及超详细搭建

文章目录 一、问题引入1. 多容器位于同一主机2. 多容器位于不同主机 二、介绍三、特性四、概念1. 节点nodes2. 服务(service)和任务(task)3. 负载均衡 五、docker网络1. overlay网络 六、docker集群搭建1. 环境介绍2. 创建集群3. 集群网络4. 加入工作节点 七、部署可视化界面po…