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

news2024/11/24 17:41:51

目录

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.coloradmin.cn/o/1689860.html

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

相关文章

第七步 实现打印函数

文章目录 前言一、如何设计我们的打印函数&#xff1f;二、实践检验&#xff01; 查看系列文章点这里&#xff1a; 操作系统真象还原 前言 现在接力棒意见交到内核手中啦&#xff0c;只不过我们的内核现在可谓是一穷二白啥都没有&#xff0c;为了让我们设计的内核能被看见被使用…

fyne网格包裹布局

fyne网格包裹布局 与之前的网格布局一样&#xff0c;网格环绕布局以网格模式创建元素排列。但是&#xff0c;此网格没有固定数量的列&#xff0c;而是为每个单元格使用固定大小&#xff0c;然后将内容流到显示项目所需的行数。 layout.NewGridWrapLayout(size) 您可以使用其中…

Mac维护神器CleanMyMac X成为你的苹果电脑得力助手

在数字化时代&#xff0c;Mac电脑已成为众多用户的首选。然而&#xff0c;随着频繁的使用和数据量的日益增长&#xff0c;许多Mac用户面临着系统杂乱、存储空间不足以及隐私保护等问题。幸运的是&#xff0c;"CleanMyMac X"这款优化和清理工具应运而生&#xff0c;它…

「网络流浅谈」最大流的应用

更好的阅读体验 二分图匹配 考虑如何将二分图匹配问题&#xff0c;转化为流网络。设置 1 1 1 个汇点和源点&#xff0c;从源点向二分图一侧的每一个点连边&#xff0c;从另一侧向汇点连边&#xff0c;边权均为 1 1 1&#xff0c;二分图中的边也全部加入&#xff0c;权值设为…

【Linux取经路】基于信号量和环形队列的生产消费者模型

文章目录 一、POSIX 信号量二、POSIX 信号量的接口2.1 sem_init——初始化信号量2.2 sem_destroy——销毁信号量2.3 sem_wait——等待信号量2.4 sem_post——发布信号量 三、基于环形队列的生产消费者模型3.1 单生产单消费模型3.2 多生产多消费模型3.3 基于任务的多生产多消费模…

构建健壮的机器学习大数据平台:任务实现与数据治理的关键

随着数据驱动决策成为现代企业的核心&#xff0c;构建安全、可靠且可扩展的大数据平台变得至关重要。这样的平台不仅需要支持复杂的机器学习任务&#xff0c;还需要在数据质量、合规性和分发方面提供严格的控制。本文旨在探讨构建大型企业机器学习大数据平台时需要考虑的关键要…

项目如何有效做资源管理?易趋项目管理软件让资源管理可视化

在项目管理的过程中&#xff0c;有效的资源管理能够确保资源得到合理的分配和使用&#xff0c;避免资源的浪费和冗余&#xff0c;进而提高整体工作效率、确保项目的成功&#xff1b;同时降低组织的运营成本。 但在项目推进过程中&#xff0c;项目经理总会面临各种资源管理的难…

基于Tensorflow卷积神经网络人脸识别公寓人员进出管理系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景与意义 随着科技的快速发展和智能化水平的提高&#xff0c;公寓管理面临着越来越多的挑战。传统的公寓…

HTML静态网页成品作业(HTML+CSS)——我的家乡云南保山介绍网页(3个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有3个页面。 二、作品演示 三、代…

轻松同步:将照片从三星手机传输到iPad的简便方法

概括 想要在新 iPad 上查看三星照片吗&#xff1f;但是&#xff0c;如果您不知道如何将照片从三星手机传输到 iPad&#xff0c;则无法在 iPad 上查看图片。为此&#xff0c;本文分享了 7 个有用的方法&#xff0c;以便您可以使用它们在不同操作系统之间轻松发送照片。现在&…

leetcode-盛水最多的容器-109

题目要求 思路 1.正常用双循环外循环i从0开始&#xff0c;内循环从height.size()-1开始去计算每一个值是可以的&#xff0c;但是因为数据量太大&#xff0c;会超时。 2.考虑到超时&#xff0c;需要优化一些&#xff0c;比如第一个选下标1&#xff0c;第二个选下标3和第一个选下…

【笔记】从零开始做一个精灵龙女-素模阶段

事前准备 1.在ps标记好位置先&#xff0c;斜方肌&#xff0c;腰线&#xff0c;耻骨&#xff0c;膝盖&#xff0c;脚 2.导入素模&#xff0c;对好位置 软选择 1.原画上半身很短&#xff0c;所以这里把上半身做的也短一些 选择上半身的点-软选择-衰减调整-箭头调整 如果要调整…

mysql数据库innodb体系结构(一、内存结构 与二、物理存储结构)

文章目录 InnoDB存储引擎结构图innoDB体系结构一、内存结构1.Buffer Pool2.Change Pool3.Log Buffer 二、物理存储结构1.系统表空间2.独立表空间3.Redo日志1、redo 日志 4.Undo日志1、undo 日志 回滚段中的UNDO日志分为两种&#xff1a;UNDO 日志存储结构 InnoDB存储引擎结构图…

Flat Ads获广东电视台报道!CEO林啸:助力更多企业实现业务全球化增长

近日,在广州举行的第四届全球产品与增长展会(PAGC2024)上,Flat Ads凭借其卓越的一站式全球化营销和创新的变现方案大放异彩,不仅吸引了众多业界目光,同时也在展会上斩获了备受瞩目的“金帆奖”,展现了其在全球化营销推广领域的卓越实力和专业服务。 在大会现场,Flat Ads的CEO林…

差分约束题解

目录 注意点&#xff1a; 思路&#xff1a; SPFA和Dij的不同点&#xff1a; Dij: SPFA: AC代码&#xff1a; 扩展&#xff1a; 题目链接&#xff1a;【模板】差分约束 - 洛谷 注意点&#xff1a; 注意这一题不能用Dij&#xff0c;只能用SPFA 因为这样子才可以得出这个不…

【简单介绍下近邻算法】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

全域运营是割韭菜吗?常见套路有哪些?

随着全域运营赛道的全面开启&#xff0c;全域运营服务商和全域运营系统的数量迅速增加&#xff0c;持续激发赛道活力的同时&#xff0c;也让一些试图用全域运营割韭菜的人有了可趁之机。 值得庆幸的是&#xff0c;由于当前全域运营赛道刚兴起不久&#xff0c;因此&#xff0c;割…

Raylib 绘制自定义字体的一种套路

Raylib 绘制自定义字体是真的难搞。我的需求是程序可以加载多种自定义字体&#xff0c;英文中文的都有。 我调试了很久成功了&#xff01; 很有用的参考&#xff0c;建议先看一遍&#xff1a; 瞿华&#xff1a;raylib绘制中文内容 个人笔记&#xff5c;Raylib 的字体使用 - …

Nginx - 健康检查终极指南:探索Upstream Check模块

文章目录 概述upstream_check_module模块安装和配置指南模块安装步骤基本配置示例详细配置说明检查类型和参数常见问题及解决方案 SSL检查和DNS解析功能SSL检查配置示例和说明配置示例 DNS解析配置示例和说明配置示例 结合实际应用场景的高级配置示例综合SSL检查与DNS解析 总结…

代码随想录算法训练营第三天| 203.移除链表元素、 707.设计链表、 206.反转链表

203.移除链表元素 题目链接&#xff1a; 203.移除链表元素 文档讲解&#xff1a;代码随想录 状态&#xff1a;没做出来&#xff0c;做题的时候定义了一个cur指针跳过了目标val遍历了一遍链表&#xff0c;实际上并没有删除该删的节点。 错误代码&#xff1a; public ListNode re…