零基础代码随想录【Day42】|| 1049. 最后一块石头的重量 II,494. 目标和,474.一和零

目录

DAY42

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

解题思路&代码

494.目标和

解题思路&代码

474.一和零

解题思路&代码


DAY42

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

力扣题目链接(opens new window)

题目难度:中等

有一堆石头,每块石头的重量都是正整数。

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

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

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

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

示例:

  • 输入:[2,7,4,1,8,1]
  • 输出:1

解释:

  • 组合 2 和 4,得到 2,所以数组转化为 [2,7,1,8,1],
  • 组合 7 和 8,得到 1,所以数组转化为 [2,1,1,1],
  • 组合 2 和 1,得到 1,所以数组转化为 [1,1,1],
  • 组合 1 和 1,得到 0,所以数组转化为 [1],这就是最优值。

本题就和 昨天的 416. 分割等和子集 很像了,可以尝试先自己思考做一做。

视频讲解:动态规划之背包问题,这个背包最多能装多少?LeetCode:1049.最后一块石头的重量II_哔哩哔哩_bilibili

代码随想录

解题思路&代码

思路:

关键点:认识到什么是应用类背包问题,此处如何联系到背包?尽量把容器分成大小相等的两堆,则另一堆是否能用数组元素填满多少则是涉及到了背包最多能装多少的问题

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

是不是感觉和昨天讲解的416. 分割等和子集 (opens new window)非常像了。

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

对应着01背包里的物品重量weight[i]和 物品价值value[i]。

1.确定dp数组以及下标的含义

dp[j]表示容量(这里说容量更形象,其实就是重量)为j的背包,最多可以背最大重量为dp[j]

可以回忆一下01背包中,dp[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[j]中的j表示容量,那么最大容量(重量)是多少呢,就是所有石头的重量和。

因为提示中给出1 <= stones.length <= 30,1 <= stones[i] <= 1000,所以最大重量就是30 * 1000 。

而我们要求的target其实只是最大重量的一半,所以dp数组开到15000大小就可以了

4.确定遍历顺序

在动态规划:关于01背包问题,你该了解这些!(滚动数组) (opens new window)中就已经说明:如果使用一维dp数组,物品遍历的for循环放在外层,遍历背包的for循环放在内层,且内层for循环倒序遍历!

  • 时间复杂度:O(m × n) , m是石头总重量(准确的说是总重量的一半),n为石头块数
  • 空间复杂度:O(m)
class Solution {public int lastStoneWeightII(int[] stones) {int sum = 0;for (int i : stones) {sum += i;}int target = sum >> 1;//初始化dp数组int[] dp = new int[target + 1];//为什么要+1,因为涉及到背包重量为0的情况,要初始化,但是实际上数组元素是不包括这个的for (int i = 0; i < stones.length; i++) {//采用倒序for (int j = target; j >= stones[i]; j--) {//两种情况,要么放,要么不放dp[j] = Math.max(dp[j], dp[j - stones[i]] + stones[i]);}}return sum - 2 * dp[target];}
}

494.目标和

力扣题目链接(opens new window)

难度:中等

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

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

示例:

  • 输入:nums: [1, 1, 1, 1, 1], S: 3
  • 输出:5

解释:

  • -1+1+1+1+1 = 3
  • +1-1+1+1+1 = 3
  • +1+1-1+1+1 = 3
  • +1+1+1-1+1 = 3
  • +1+1+1+1-1 = 3

一共有5种方法让最终目标和为3。

大家重点理解 递推公式:dp[j] += dp[j - nums[i]],这个公式后面的提问 我们还会用到。

视频讲解:动态规划之背包问题,装满背包有多少种方法?| LeetCode:494.目标和_哔哩哔哩_bilibili

代码随想录

 

解题思路&代码

思路:

本题要如何使表达式结果为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的组合

再回归到01背包问题,为什么是01背包呢?

因为每个物品(题目中的1)只用一次!

这次和之前遇到的背包问题不一样了,之前都是求容量为j的背包,最多能装多少。

本题则是装满有几种方法。其实这就是一个组合问题了。

1.确定dp数组以及下标的含义

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

其实也可以使用二维dp数组来求解本题,dp[i][j]:使用 下标为[0, i]的nums[i]能够凑满j(包括j)这么大容量的包,有dp[i][j]种方法。

2.确定递推公式

有哪些来源可以推出dp[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]] 累加起来。

所以求组合类问题的公式,都是类似这种:

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

3.dp数组如何初始化

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

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

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

4.确定遍历顺序

在动态规划:关于01背包问题,你该了解这些!(滚动数组) (opens new window)中,我们讲过对于01背包问题一维dp的遍历,nums放在外循环,target在内循环,且内循环倒序。

5.举例推导dp数组

输入:nums: [1, 1, 1, 1, 1], S: 3

bagSize = (S + sum) / 2 = (3 + 5) / 2 = 4

dp数组状态变化如下:

  • 时间复杂度:O(n × m),n为正数个数,m为背包容量
  • 空间复杂度:O(m),m为背包容量
class Solution {public int findTargetSumWays(int[] nums, int target) {int sum = 0;for (int i = 0; i < nums.length; i++) sum += nums[i];//如果target的绝对值大于sum,那么是没有方案的if (Math.abs(target) > sum) return 0;//如果(target+sum)除以2的余数不为0,也是没有方案的if ((target + sum) % 2 == 1) return 0;int bagSize = (target + sum) / 2;int[] dp = new int[bagSize + 1];dp[0] = 1;for (int i = 0; i < nums.length; i++) {for (int j = bagSize; j >= nums[i]; j--) {dp[j] += dp[j - nums[i]];}}return dp[bagSize];}
}

474.一和零

力扣题目链接(opens new window)

给你一个二进制字符串数组 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 。

通过这道题目,大家先粗略了解, 01背包,完全背包,多重背包的区别,不过不用细扣,因为后面 对于 完全背包,多重背包 还有单独讲解。

视频讲解:动态规划之背包问题,装满这个背包最多用多少个物品?| LeetCode:474.一和零_哔哩哔哩_bilibili

代码随想录

解题思路&代码

思路:

本题并不是多重背包,再来看一下这个图,捋清几种背包的关系

416.分割等和子集1

多重背包是每个物品,数量不同的情况。

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

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

理解成多重背包的同学主要是把m和n混淆为物品了,感觉这是不同数量的物品,所以以为是多重背包。

但本题其实是01背包问题!

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

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

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

2.确定递推公式

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背包! 只不过物品的重量有了两个维度而已。

3.dp数组如何初始化

在动态规划:关于01背包问题,你该了解这些!(滚动数组) (opens new window)中已经讲解了,01背包的dp数组初始化为0就可以。

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

4.确定遍历顺序

在动态规划:关于01背包问题,你该了解这些!(滚动数组) (opens new window)中,我们讲到了01背包为什么一定是外层for循环遍历物品,内层for循环遍历背包容量且从后向前遍历!

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

  • 时间复杂度: O(kmn),k 为strs的长度
  • 空间复杂度: O(mn) 
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) {//正序遍历物品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.mzph.cn/bicheng/14804.shtml

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

相关文章

(Qt) 默认QtWidget应用包含什么?

文章目录 ⭐前言⭐创建&#x1f6e0;️选择一个模板&#x1f6e0;️Location&#x1f6e0;️构建系统&#x1f6e0;️Details&#x1f6e0;️Translation&#x1f6e0;️构建套件(Kit)&#x1f6e0;️汇总 ⭐项目⚒️概要⚒️构建步骤⚒️清除步骤 ⭐Code&#x1f526;untitled…

【EasyX】快速入门——消息处理,音频

1.消息处理 我们先看看什么是消息 1.1.获取消息 想要获取消息,就必须学会getmessage函数 1.1.1.getmessage函数 有两个重载版本,它们的作用是一样的 参数filter可以筛选我们需要的消息类型 我们看看参数filter的取值 当然我们可以使用位运算组合这些值 例如,我们…

华为CE6851-48S6Q-HI升级设备版本及补丁

文章目录 升级前准备工作笔记本和交换机设备配置互联地址启用FTP设备访问FTP设备升级系统版本及补丁 升级前准备工作 使用MobaXterm远程工具连接设备&#xff0c;并作为FTP服务器准备升级所需的版本文件及补丁文件 笔记本和交换机设备配置互联地址 在交换机接口配置IP&#…

Facebook隐私保护:数据安全的前沿挑战

在数字化时代&#xff0c;随着社交媒体的普及和应用&#xff0c;个人数据的隐私保护问题日益受到关注。作为全球最大的社交平台之一&#xff0c;Facebook承载了数十亿用户的社交活动和信息交流&#xff0c;但与此同时&#xff0c;也面临着来自内外部的数据安全挑战。本文将深入…

AWS Elastic Beanstalk 监控可观测最佳实践

一、概述 Amazon Web Services (AWS) 包含一百多种服务&#xff0c;每项服务都针对一个功能领域。服务的多样性可让您灵活地管理 AWS 基础设施&#xff0c;然而&#xff0c;判断应使用哪些服务以及如何进行预配置可能会非常困难。借助 Elastic Beanstalk&#xff0c;可以在 AW…

【LinuxC语言】一切皆文件的理念

文章目录 引言一、什么是“一切皆文件”&#xff1f;1. 文件柜的类比2. 统一的操作方式3. 举个具体例子4. 设备文件5. 进程和网络连接6. 简化管理 二、这一设计的优势1. 统一接口2. 灵活性3. 简化了系统管理4. 增强了系统安全性 结论 引言 Linux 操作系统以其独特的设计理念和…

如何使用JMeter 进行全链路压测

使用 JMeter 进行全链路压测&#xff1a;详细步骤指南 全链路压测旨在测试整个系统的性能&#xff0c;包括所有的组件和服务。通过 Apache JMeter 进行全链路压测&#xff0c;可以模拟真实用户行为&#xff0c;测试系统在高负载下的表现。以下是详细的步骤指南&#xff0c;分为…

AWTK实现汽车仪表Cluster/DashBoard嵌入式GUI开发(七):快启

前言: 汽车仪表是人们了解汽车状况的窗口,而仪表中的大部分信息都是以指示灯形式显示给驾驶者。仪表指示灯图案都较为抽象,对驾驶不熟悉的人在理解仪表指示灯含义方面存在不同程度的困难,尤其对于驾驶新手,如果对指示灯的含义不求甚解,有可能影响驾驶的安全性。即使是对…

Pytest框架实战二

在Pytest框架实战一中详细地介绍了Pytest测试框架在参数化以及Fixture函数在API测试领域的实战案例以及具体的应用。本文章接着上个文章的内容继续阐述Pytest测试框架优秀的特性以及在自动化测试领域的实战。 conftest.py 在上一篇文章中阐述到Fixture函数的特性&#xff0c;第…

shell循环

一、for循环 用法&#xff1a; for 变量 in 取值列表 do 命令序列 done 例1&#xff1a;打印1到10的数字列表 #!/bin/bashfor i in {1..10} do echo $i done 例2&#xff1a;#批量添加用户,用户名存放在users.txt文件中&#xff0c;每行一个,初始密码均设为123456 #!/bin/bas…

KMP算法【C++】

KMP算法测试 KMP 算法详解 根据解释写出对应的C代码进行测试&#xff0c;也可以再整理成一个函数 #include <iostream> #include <vector>class KMP { private:std::string m_pat;//被匹配的字符串std::vector<std::vector<int>> m_dp;//状态二维数组…

怎样解决Redis高并发竞争Key难点?

Redis作为一种高性能的键值存储系统&#xff0c;在现代分布式系统中发挥着重要作用。然而&#xff0c;高并发场景下对同一Key的操作可能引发竞争条件&#xff0c;给系统稳定性和数据一致性带来挑战。本文将探讨如何解决这一问题&#xff0c;为读者提供有效的应对策略。 1. Red…

【002】FlexBison实现原理

0. 前言 Flex和Bison是用于构建处理结构化输入的程序的工具。它们最初是用于构建编译器的工具&#xff0c;但它们已被证明在许多其他领域都很有用。 &#xfeff; 在第一章中&#xff0c;我们将首先看一点(但不是太多)它们背后的理论&#xff0c;然后我们将深入研究一些使用它…

Mysql和Postgresql创建用户和授权命令

Mysql和Postgresql创建用户和授权命令 MySQL/MariaDB/TiDB mysql -uroot -P3306 -p 输入密码&#xff1a;xxx create user user1% identified by xxx; grant all privileges on *.* to user1%; create user user2% identified by xxx; grant all privileges on *.* to user2%;…

Winform /C# 截图当前窗体,指定区域,当前屏幕

1.当前窗体 public static Image CaptureControl(Control ctrl){System.Drawing.Bitmap bmp new System.Drawing.Bitmap(ctrl.Width, ctrl.Height);ctrl.DrawToBitmap(bmp, new Rectangle(0, 0, ctrl.Width, ctrl.Height));return bmp;}private void DownLoad(){string filePa…

java类中运行main方法时报错:找不到或无法加载主类 XXX

运行main类报了这个错 错误: 找不到或无法加载主类 XXX 经过好一番查证才找出了问题所在 原因是 maven项目的provided导致的&#xff0c;现在记录一下。 将pom.xml中标注provided的注释掉&#xff0c;就不报错了。

ERROR [internal] load metadata for docker.io/library/node:20-alpine

docker编译时报错&#xff0c;除标题外&#xff0c;还报如下信息 ERROR: failed to solve: node:20-alpine: failed to resolve source metadata for docker.io/library/node:20-alpine: failed to do request: Head "https://registry-1.docker.io/v2/library/node/mani…

常用个人信息

目录 常用联系方式我的自动思维常用媒体专业相关康米相关黑历史 常用联系方式 QQ&#xff1a;2868679921 微信&#xff1a;Commieee 邮箱&#xff1a;sharvefoxmail.com 我的自动思维 常用媒体 哔哩哔哩 专业相关 博客 康米相关 QQ&#xff1a;1203361015 黑历史 贴吧…

PyQt5学习系列之QMetaObject.connectSlotsByName

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 学习记录 QMetaObject.connectSlotsByName——自动将信号连接到槽&#xff08;函数&#xff09; 例如&#xff1a; from PyQt5.QtWidgets import QMainWindow, QPushButton from PyQt5.QtCore…

哪些类型的产品适合用3D形式展示?

随着3D技术的蓬勃发展&#xff0c;众多品牌和企业纷纷投身3D数字化浪潮&#xff0c;将产品打造成逼真的3D模型进行展示&#xff0c;消费者可以更加直观地了解产品的特点和优势&#xff0c;从而做出更明智的购买决策。 哪些产品适合3D交互展示&#xff1f; 产品3D交互展示具有直…