LeetCode刷题笔记【33】:动态规划专题-5(最后一块石头的重量 II、目标和、一和零)

news2025/7/17 16:07:54

文章目录

  • 前置知识
  • 1049. 最后一块石头的重量 II
    • 题目描述
    • 解题思路
    • 代码
  • 494. 目标和
    • 题目描述
    • 用回溯算法
    • 转换为背包问题动态规划
  • 474.一和零
    • 题目描述
    • 解题思路
    • 代码
  • 总结

前置知识

今天是动态规划专题的第5篇, 也是背包问题的第2篇.
所以本文和动态规划专题的1~3弱相关, 和上一篇, 也就是动态规划-4强相关.

相比于昨天的经典背包问题的思路与模板, 今天侧重于如何将其他问题理解为背包问题, 并且如何对具体的情景进行调整.
并且今天的三道题都是广义的"01背包问题", 即"物品只有选择/不选择两种情况".

参考文章:
LeetCode刷题笔记【29】:动态规划专题-1(斐波那契数、爬楼梯、使用最小花费爬楼梯)
LeetCode刷题笔记【30】:动态规划专题-2(不同路径、不同路径 II)
LeetCode刷题笔记【31】:动态规划专题-3(整数拆分、不同的二叉搜索树)
LeetCode刷题笔记【32】:动态规划专题-4(二维背包问题、一维背包问题、分割等和子集)

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

题目描述

在这里插入图片描述

LeetCode链接:https://leetcode.cn/problems/last-stone-weight-ii/description/

解题思路

参考昨天最后一题<416. 分割等和子集>, 昨天是要我们选出两组数, 然后让两组数的和相同;
今天是让我们选出一对儿一对儿的石头, 互相碰, 让最后剩下的石头最小; (看似差别较大)

但其实可以转化为:“选出两组石头, 让两组石头互相碰, 从而让剩下的结果最小

这样一来, 就可以使用和<416. 分割等和子集>一样的思路, 先求sum, 然后将sum/2作为bagSize(target), 使用背包问题的过程, 从而求得dp[target]的值, 也就是"面对target这么大的背包, 我们最多能装多少石头".

唯一需要注意的是, 最后的结果应该是 sum-2*dp[target], 因为是求剩下了多少石头嘛.

代码

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

494. 目标和

题目描述

截图

LeetCode链接:https://leetcode.cn/problems/target-sum/description/

用回溯算法

① 回溯遍历穷举(虽然时间复杂度非常高, 但是高低是通过了)

class Solution {
private:
    int ans=0;
    int curSum=0;
    void backtrack(vector<int>& nums, int target, int index){
        if(index>=nums.size()){
            if(curSum==target)
                ans++;
            return;
        }
        curSum += nums[index];
        backtrack(nums, target, index+1);
        curSum -= nums[index]*2;
        backtrack(nums, target, index+1);
        curSum += nums[index];
        return;
    }
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        backtrack(nums, target, 0);
        return ans;
    }
};

转换为背包问题动态规划

② 转换为背包问题, 动态规划
既然最后可以得到target, 那么一定可以将所有数分为leftright两组, 有如下关系:
left+right=sum, left-right=terget
推导得到: left = (sum+target)/2, 这样一来, 问题就转化为"nums中有多少种数字组合, 可以让和为(sum+target)/2"

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        int sum=0;
        for(int num : nums)
            sum += num;

        if(abs(target)>sum)
            return 0;
        if((sum+target)%2==1)
            return 0;

        int left = (sum+target)/2;
        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];
    }
};

这还有一个问题, 就是关于递推公式为什么是dp[j] += dp[j-nums[i]];
其实写成 dp[j] = dp[j] + dp[j-nums[i]] 更方便理解, 解释起来就是:
① 现在的背包容量是j
② 一方面之前还没有物品i的时候, 我有dp[i]种将容量为j的背包装满的方法(上一行中的内容)
③ 现在有了物品i, 其重量是nums[i], 那么此时的装满背包的方法, 一方面要考虑原有的dp[i], 还要考虑装入物品i后, 装满剩余空间的方法数量(dp[j-nums[i]])

所以面对容量为j的背包, 和0~i种物品, 有dp[j] = dp[j] + dp[j-nums[i]]种装包方法

在这里插入图片描述
如果将一维dp数组展开成二维, 展现其更新推导过程, 则如上图所示

还有一个点是关于初始化, 为什么要让dp[0]=1, 我的理解是对于容量为0的背包, 你手上一个物品都没有(0个物品), 那么你就只有1种方法: 啥都不装. 所以为1.

474.一和零

题目描述

截图

LeetCode链接:xxx(记得加点击跳转链接)

解题思路

<代>: 其实还是01背包问题, 但此时背包中有两个bagSize的维度
递推公式是: dp[i][j] = max(dp[i][j], dp[i-zeroNum][i-oneNum]+1)
其中zeroNumoneNum当前0和1的数量

代码

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 zeroNum = 0, oneNum = 0;
            for(int 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];
    }
};

总结

简单01背包问题分割等和子串最后一块石头的重量目标和
问什么问题面对大小为bagSize的背包和n件物品, 怎么装收益最大面对大小为sum/2的背包, 用nums中的num作为物品, 能不能将背包装满面对sum/2的背包, 我用这些石头尽量多装, 剩下的空间最少是多少面对大小为(sum+target)/2的背包, 我用nums中的num作为物品来装满它, 有几种装法?
背包大小bagSizetarget=sum/2target=sum/2left=(sum+target)/2
是否要装满不一定需要, 否则返回false不一定, 求最少剩下多少空间一定
返回结果最大收益dp.back() / dp.(bagSize)装满了(dp[target]==target, 则true)/没装满(dp[target]!=target, 则false)sum-2*dp[target]dp[left]
dp数组的含义背包大小j, 有0~i物品, 最大收益同左, 但weightvalue都用nums代替同左左, 但stones同时担任weightvalue的作用背包大小j, 有0~i物品, 装满背包的方法数量
递推公式dp[j]=max(dp[j], value[i]+dp[j-weight[i]])dp[j]=max(dp[j], nums[i]+dp[j-nums[i]])dp[j]=max(dp[j], stones[i]+dp[j-stones[i]])dp[j] = dp[j]+dp[j-nums[i]]
trick二维换一维, 偷空间复杂度sum%2==1了直接return false和左右两边需要检测奇数偶数不同, 虽然这里也有target=sum/2, 但可以直接用int性质向下取整sum%2==1 或者 (sum+target)%2==1了直接return false
备注遇到其他问题想不出来了, 就往这个经典问题上靠, 甚至别强求一维背包, 画一下二维背包帮助理解类似于右value数组和weight数组意义重合, 二者的功能被stones数组同时担任可以看出和前三个几乎不是一卦的, 要注意区分, 以及理解递推公式

本文参考:
最后一块石头的重量 II
目标和
一和零

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

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

相关文章

趣解设计模式之《小店儿菜单的故事》

〇、小故事 在一座小镇上&#xff0c;有两家特别有名气的小店&#xff0c;一家是远近闻名的早餐店&#xff0c;它家的早餐特别好吃&#xff0c;每天早上都能排起长长的队伍&#xff1b;另一家是个蛋糕店&#xff0c;他家是专门从法国请来的蛋糕师傅&#xff0c;蛋糕的香味真是…

uniapp微信小程序《隐私保护协议》弹窗处理流程

背景 《关于小程序隐私保护指引设置的公告》 《小程序隐私协议开发指南》 流程 1.第一步 必须设置且审核通过&#xff01;&#xff01;&#xff01; 2.第二步 uniapp在manifest.json中添加&#xff01;&#xff01;&#xff01; /* 在 2023年9月15号之前&#xff0c;在 ap…

汽车电子智能仓储系统的发展趋势与应用探索

现代汽车制造业中的仓储管理一直面临着多种挑战。仓库中物料的数量种类繁多&#xff0c;寻找物料耗时长、困难大。盘点过程耗费人力多、成本高、速度慢。管理无法达到先进先出的原则&#xff0c;也无法进行精准追溯。此外&#xff0c;多发、少发、错料等问题时有发生。仓库中的…

docker学习:dockerfile和docker-compose

学习如何使用dockerfile 以下内容&#xff0c;部分来自gpt生成&#xff0c;里面的描述可能会出现问题&#xff0c;但代码部分&#xff0c;我都会进行测试。 1. 需求 对于一个docker&#xff0c;例如python&#xff0c;我们需要其在构建成容器时&#xff0c;就有np。有以下两种方…

Linux内核源码分析 (B.x)Linux物理内存的初始化

Linux内核源码分析 (B.x)Linux物理内存的初始化 文章目录 Linux内核源码分析 (B.x)Linux物理内存的初始化一、DDR简介二、内存节点三、内存管理区域ZONE四、 struct zone五、 struct page六、mem_map数组七、伙伴系统简介八、迁移类型九、内存初始化十、总结 一、DDR简介 详细可…

电脑msvcp140.dll丢失问题的三种解决方法分享,快速修复dll问题

在我们的日常生活中&#xff0c;计算机已经成为了我们工作、学习和娱乐的重要工具。然而&#xff0c;在使用计算机的过程中&#xff0c;我们可能会遇到各种问题&#xff0c;其中之一就是 msvcp140.dll 丢失的困扰。本文将详细介绍 msvcp140.dll 丢失的原因、解决方法以及预防措…

可变参数JAVA

public class Main {public static void main(String[] args) {//方法形参的个数是可以变化的//格式&#xff1a;属性类型...名字System.out.println(getSum(1,2,3,4,5,6,7,8));}//通过键值对对象来遍历&#xff1b;public static int getSum(int a,int...args){//可变参数;int…

AirTag是什么?高精度测距定位防丢,UWB厘米级方案应用

随着科技的不断发展&#xff0c;超宽带&#xff08;UWB&#xff09;技术作为一种新兴的无线通信技术&#xff0c;逐渐受到人们的关注和追捧。 UWB技术以其传输速率高、抗干扰性强、带宽极宽、功耗低、安全性高、穿透力强、定位精准等优势&#xff0c;在众多领域具有广泛的应用…

输电线路故障数据集(基于simulink仿真批量生成故障数据,单相接地故障、两相接地故障、两相间短路故障、三相接地故障、三相间短路故障和正常)

分别获取单相接地故障、两相接地故障、两相间短路故障、三相接地故障、三相间短路故障和正常状态下的电流&#xff08;Ia,Ib,Ic&#xff09;大小和电压&#xff08;Ua,Ub和Uc&#xff09;大小。每种故障下获取1300行左右的数据 将故障区分为具体的不同类型&#xff08;一共五种…

JetBrains设置inline hint的背景色、前景色

如题。修改IDE的hint前景色和背景色。 修改后结果&#xff1a;

为什么DasViewer打开之后一直白屏?如图

答&#xff1a;这种情况可以检查一下电脑的集显驱动。 DasViewer是由大势智慧自主研发的免费的实景三维模型浏览器,采用多细节层次模型逐步自适应加载技术,让用户在极低的电脑配置下,也能流畅的加载较大规模实景三维模型,提供方便快捷的数据浏览操作。#DasViewer##实景三维##三…

跟踪源码技巧+阅读源码工具Sourcetrail

基于Eclipse IDE 1、Quick Type Hierarchy 快速查看类继承体系 &#xff08; 快捷键&#xff1a;Ctrl T&#xff09; 查看类很多人可能都知道&#xff0c;可源码阅读的时候更多用来查看方法体系更重要&#xff0c;可以方便快速的定位到方法的实现类。如&#xff1a; 此时如…

Mendelay-文献管理软件使用教程

Mendelay-文献管理软件 注册账号 注册账号 打开官网&#xff0c;注册个人账号 通过邮箱就可以注册账号啦&#xff0c;这是登录后的页面&#xff0c;并下载Mendeley客户端。 安装好客户端&#xff0c;打开软件首先登录以上注册的账号&#xff0c;则可进入客户端首页。

《安富莱嵌入式周报》第322期:自制10KV电子负载,史上最详细的电池系列资料,创意洞洞板任意互联,开源USB分析仪,英特尔雷电5, QNX功能安全免费课程

周报汇总地址&#xff1a;嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 视频版&#xff1a; https://www.bilibili.com/video/BV1M8411q7dw/ 《安富莱嵌入式周报》第322期&#xff1a;自制10K…

nvue文件中@click.stop失效

在nvue文件中在子元素使用click.stop失效&#xff0c;父元素的事件触发了 在uniapp开发中nvue文件是跟vue文件是不一样的&#xff0c;就比如click.stop阻止点击事件继续传播就失效了&#xff0c;这时我们需要在子元素事件中添加条件编译&#xff0c;这样就会解决这个问题 // …

图论第三天|130. 被围绕的区域、417. 太平洋大西洋水流问题、827. 最大人工岛

130. 被围绕的区域 文档讲解 &#xff1a;代码随想录 - 130. 被围绕的区域 状态&#xff1a;开始学习。 思路&#xff1a; 步骤一&#xff1a; 深搜或者广搜将地图周边的 ‘O’ 全部改成 ’A’&#xff0c;如图所示&#xff1a; 步骤二&#xff1a; 再遍历地图&#xff0c;将 …

记录一次使用网云穿实现内网穿透操作

记录一次使用网云穿实现内网穿透操作 摘要 这段时间也很少写博客了,一方面工作表较忙,一方面觉得有些东西在百度上都能找到,甚至比我自己记录的详细,有些笔记也就没打, 这次记录笔记主要是觉得这个 网云穿 很好用,分享给大家. 1 什么是内网穿透? 内网穿透也叫内网映射&#xf…

zookeeper最基础教程

文章目录 一、简介1、工作机制2、特点3、数据结构4、应用场景5、选举机制 二、软件安装1、单机版安装2、集群安装3、配置参数解读(zoo.cfg)4、ZK集群启动脚本 三、命令行操作1、语法2、使用3、节点相关4、监听器原理5、节点删除与查看 三、写数据流程 一、简介 1、工作机制 官…

输电线路故障数据集(单相接地故障、两相接地故障、两相间短路故障、三相间短路故障)

1.数据集介绍 将故障区分为具体的不同类型&#xff1a;单相短路故障、两相接地短路故障、两相相间故障、三相相间短路故障。每类有1300行数据左右&#xff0c;这里随意举出每种类别的两个样本进行展示。 GCBAIaIbIcVaVbVc1001-151.2918124-9.67745156385.800162260.400749853…

Hadoop设置固定ip无效的解决办法

今天配置Hadoop的时候&#xff0c;执行vi /etc/sysconfig/network-scripts/ifcfg-ens33修改网络配置文件后&#xff0c;一切正常&#xff0c;但重启后IP改变了&#xff0c;并且在修改以及重启网络连接数次后&#xff0c;IP依旧不按照我在ifcfg-ens33中配置的那样&#xff0c;检…