当前位置: 首页 > news >正文

DAY42 1049.最后一块石头的重量II + 494.目标和 + 474.一和零

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

题目要求:有一堆石头,每块石头的重量都是正整数。

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

如果 x == y,那么两块石头都会被完全粉碎;

如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。

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

思路

目标是尽量让石头分成重量相同的两堆,相撞之后剩下的石头最小,这样就转化成01背包问题了。

dp[j]表示容量为j的背包,可以装载的最大重量为dp[j]

遍历顺序:如果使用一维dp数组,物品遍历的for循环放在外层,遍历背包的for循环房子啊内层,且内层for循环倒序遍历。

分成两堆石头,一堆石头的总重量是dp[target],另一堆就是sum-dp[target]

在计算target时候,target=sum/2是向下取整。所以sum-dp[target]一定大于等于dp[target]。那么相撞后剩下的最小石头重量就是(sum-dp[target])-dp[target]

class Solution {
public:int lastStoneWeightII(vector<int>& stones) {vector<int> dp(15001, 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]);}}return sum - dp[target] - dp[target];}
};
  • 时间复杂度:O(m × n) , m是石头总重量(准确的说是总重量的一半),n为石头块数
  • 空间复杂度:O(m)

494.目标和

题目要求:给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。

返回可以使最终数组和为目标数 S 的所有添加符号的方法数。

思路

目前我们已经有了目标target=s,假设加法的总和为x,那么减法对应的总和就是sum-x。所以我们要求的是x-(sum-x)=target,x=(target+sum)/2。此时问题就转化为,装满容量为x的背包有几种方法。

x的计算是向下取整的,所以如果target+sum为奇数,那么本提无解。如果S的绝对值大于sum也是无解的。

装满背包有几种方法,其实就是一个组合问题了。

递推公式:只要有nums[i],凑成dp[j]就有dp[j - nums[i]] 种方法。

那么凑整dp[5]有多少方法呢,也就是把 所有的 dp[j - nums[i]] 累加起来。

dp数组的初始化:

从递推公式可以看出,在初始化的时候dp[0] 一定要初始化为1,因为dp[0]是在公式中一切递推结果的起源,如果dp[0]是0的话,递推结果将都是0。

这里有录友可能认为从dp数组定义来说 dp[0] 应该是0,也有录友认为dp[0]应该是1。

其实不要硬去解释它的含义,咱就把 dp[0]的情况带入本题看看应该等于多少。

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

所以本题我们应该初始化 dp[0] 为 1。

可能有同学想了,那 如果是 数组[0,0,0,0,0] target = 0 呢。

其实 此时最终的dp[0] = 32,也就是这五个零 子集的所有组合情况,但此dp[0]非彼dp[0],dp[0]能算出32,其基础是因为dp[0] = 1 累加起来的。

dp[j]其他下标对应的数值也应该初始化为0,从递推公式也可以看出,dp[j]要保证是0的初始值,才能正确的由dp[j - nums[i]]推导出来。

确定遍历顺序:

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

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

474.一和零

题目要求:给你一个二进制字符串数组 strs 和两个整数 m 和 n 。

请你找出并返回 strs 的最大子集的大小,该子集中 最多 有 m 个 0 和 n 个 1 。

如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。

示例 1:

  • 输入:strs = ["10", "0001", "111001", "1", "0"], m = 5, n = 3

  • 输出:4

  • 解释:最多有 5 个 0 和 3 个 1 的最大子集是 {"10","0001","1","0"} ,因此答案是 4 。 其他满足题意但较小的子集包括 {"0001","1"} 和 {"10","1","0"} 。{"111001"} 不满足题意,因为它含 4 个 1 ,大于 n 的值 3 。

思路

本题中strs 数组里的元素就是物品,每个物品都是一个!

而m 和 n相当于是一个背包,两个维度的背包

只不过这个背包有两个维度,一个是m 一个是n,而不同长度的字符串就是不同大小的待装物品。

  • 确定dp数组(dp table)以及下标的含义

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

  • 确定递推公式

dp[i][j] 可以由前一个strs里的字符串推导出来,strs里的字符串有zeroNum个0,oneNum个1。

dp[i][j] 就可以是 dp[i - zeroNum][j - oneNum] + 1。

然后我们在遍历的过程中,取dp[i][j]的最大值。

所以递推公式:dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);

此时大家可以回想一下01背包的递推公式:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

对比一下就会发现,字符串的zeroNum和oneNum相当于物品的重量(weight[i]),字符串本身的个数相当于物品的价值(value[i])。

这就是一个典型的01背包! 只不过物品的重量有了两个维度而已。

  • dp数组如何初始化

因为物品价值不会是负数,初始为0,保证递推的时候dp[i][j]不会被初始值覆盖。

  • 确定遍历顺序

01背包一定是外层for循环遍历物品,内层for循环遍历背包容量且从后向前遍历!

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

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 oneNum = 0, zeroNum = 0;for (char c : str) {if (c == '0') zeroNum++;else oneNum++;}for (int i = m; i >= zeroNum; --i) {for (int j = n; j >= oneNum; --j) {dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);}}}return dp[m][n];}
};
  • 时间复杂度: O(kmn),k 为strs的长度
  • 空间复杂度: O(mn)

相关文章:

DAY42 1049.最后一块石头的重量II + 494.目标和 + 474.一和零

1049.最后一块石头的重量II 题目要求&#xff1a;有一堆石头&#xff0c;每块石头的重量都是正整数。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x < y。那么粉碎的可能结果如下&#xff1a; …...

uniapp原生插件之安卓华为统一扫码HMS Scan Kit

插件介绍 华为统一扫码服务&#xff08;Scan Kit&#xff09;提供便捷的条形码和二维码扫描、解析、生成能力 插件地址 安卓华为统一扫码HMS Scan Kit - DCloud 插件市场 超级福利 uniapp 插件购买超级福利 详细使用文档 详细使用文档 插件申请权限 android.permi…...

数模国赛——多波束测线问题模型建立研究分析

第一次参加数模国赛&#xff0c;太菜了~~~~意难平 问题一 画出与测线方向垂直的平面和海底坡面的交线构成一条与水平面夹角为&#x1d400;的斜线的情况下的示意图进行分析&#xff0c;将覆盖宽度分为左覆盖宽度和右覆盖宽度&#xff0c;求出它们与海水深度和&#x1d400;、…...

[AUTOSAR][诊断管理][ECU][$37] 请求退出传输。终止数据传输的(上传/下载)

文章目录 一、简介二、服务请求报文定义肯定响应支持的NRC三、示例流程Step 1:Step 2:报文示例:Step 1:请求RequestDownload(0x34)服务Step 2:请求TransferData (0x36)服务,传输数据Step 3:请求RequestTransferExit(0x37)服务总结:三、示例代码37_req_transfer_e…...

vue+canvas实现横跨整个页面的动态的波浪线(贝塞尔曲线)

本来写这个特效 我打算用css实现的,结果是一波三折,我太难了,最终没能用css实现,转战了canvas来实现。来吧先看效果图 当然这个图的波浪高度、频率、位置、速度都是可调的,请根据自己的需求调整,如果你讲波浪什么的调大一下 还有有摆动的效果哦。 以下是完整代码 <…...

LeetCode算法题解|​ 669. 修剪二叉搜索树​、108. 将有序数组转换为二叉搜索树、​538. 把二叉搜索树转换为累加树​

一、LeetCode 669. 修剪二叉搜索树​ 题目链接&#xff1a;669. 修剪二叉搜索树 题目描述&#xff1a; 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变…...

直播界很火的无线领夹麦克风快充方案 Type-C接口 PD快充+无线麦克风可同时进行

当前市场上流行一款很火的直播神器&#xff0c;无线领夹麦克风&#xff08;MIC&#xff09;&#xff0c;应用于网红直播&#xff0c;网课教学&#xff0c;采访录音&#xff0c;视频录制&#xff0c;视频会议等等场景。 麦克风对我们来说并不陌生&#xff0c;而且品类有很多。随…...

Jmeter 汉化中文语言

找到 bin -> jmeter.propertise 修改参数&#xff1a;languageen --> languagazh_CN OK&#xff01;...

centos9 stream 下 rabbitmq高可用集群搭建及使用

RabbitMQ是一种常用的消息队列系统&#xff0c;可以快速搭建一个高可用的集群环境&#xff0c;以提高系统的弹性和可靠性。下面是搭建RabbitMQ集群的步骤&#xff1a; 基于centos9 stream系统 1. 安装Erlang和RabbitMQ 首先需要在所有节点上安装Erlang和RabbitMQ。建议使用官…...

代码随想录算法训练营第10天|232. 用栈实现队列 225. 用队列实现栈

JAVA代码编写 232. 用栈实现队列 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、pop、peek、empty&#xff09;&#xff1a; 实现 MyQueue 类&#xff1a; void push(int x) 将元素 x 推到队列的末尾int pop() 从队列的开头移除…...

线上Kafka集群如何调整消息存储时间

这里是weihubeats,觉得文章不错可以关注公众号小奏技术&#xff0c;文章首发。拒绝营销号&#xff0c;拒绝标题党 Kafka版本 kafka_2.13-3.5.0 背景 Kafka 默认消息存储时间为7天&#xff0c;实际线上的业务使用Kafka更多的是一些数据统计之类的业务&#xff0c;大多是朝生夕…...

[迁移学习]DA-DETR基于信息融合的自适应检测模型

原文标题为&#xff1a;DA-DETR: Domain Adaptive Detection Transformer with Information Fusion&#xff1b;发表于CVPR2023 一、概述 本文所描述的模型基于DETR&#xff0c;DETR网络是一种基于Transformer的目标检测网络&#xff0c;详细原理可以参见往期文章&#xff1a;…...

【MATLAB】全网唯一的13种信号分解+FFT傅里叶频谱变换联合算法全家桶

有意向获取代码&#xff0c;请转文末观看代码获取方式~ 大家吃一顿火锅的价格便可以拥有13种信号分解FFT傅里叶频谱变换联合算法&#xff0c;绝对不亏&#xff0c;知识付费是现今时代的趋势&#xff0c;而且都是我精心制作的教程&#xff0c;有问题可随时反馈~也可单独获取某一…...

Nginx安装与配置

1.下载安装包 官网下载地址&#xff1a;nginx: download 可以先将安装包下载到本地再传到服务器&#xff0c;或者直接用wget命令将安装包下载到服务器&#xff0c;这里我们直接将安装包下载到服务器上。未安装wget命令的需要先安装wget&#xff0c;yum install -y wget [root…...

linux笔记总结-基本命令

参考&#xff1a; 1.Linux 和Windows比 比较 &#xff08;了解&#xff09; 1. 记住一句经典的话&#xff1a;在 Linux 世界里&#xff0c;一切皆文件 2. Linux目录结构 /lib • 系统开机所需要最基本的动态连接共享库&#xff0c;其作用类似于Windows里的DLL文件。几 乎所有…...

[PHP]禅道项目管理软件ZenTaoPMS源码包 v16.4

禅道项目管理软件ZenTaoPMS一键安装包是一款国产的开源项目管理软件。它集产品管理、项目管理、质量管理、文档管理、组织管理和事务管理于一体&#xff0c;是一款专业的研发项目管理软件&#xff0c;完整地覆盖了项目管理的核心流程。注重实效的管理思想&#xff0c;合理的软件…...

Required String parameter ‘name‘ is not present

[org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter name is not present] 服务端有参数name&#xff0c;客户端没有传上来...

路由器基础(五): OSPF原理与配置

开放式最短路径优先 (Open Shortest Path First,OSPF) 是一个内部网关协议 (Interior Gateway Protocol,IGP),用于在单一自治系统(Autonomous System,AS) 内决策路由。OSPF 适合小型、中型、较大规模网络。OSPF 采用Dijkstra的最短路径优先算法 (Shortest Pat…...

Leetcode1128. 等价多米诺骨牌对的数量

Every day a Leetcode 题目来源&#xff1a;1128. 等价多米诺骨牌对的数量 解法1&#xff1a;暴力 代码&#xff1a; class Solution { public:int numEquivDominoPairs(vector<vector<int>> &dominoes){int n dominoes.size(), count 0;for (int i 0;…...

Dev-C调试的基本方法2-2

3.3 跳出函数 在图6所示的状态下&#xff0c;点击单步调试&#xff08;F7&#xff09;会继续调试下一行&#xff0c;而如果想结束在函数中的调试&#xff0c;则点击图4③所示的跳出函数&#xff0c;或CtrlF8按键跳出f()函数&#xff0c;程序将会停在图5所示的第11行处。 3.4 …...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...