代码随想录算法训练营第四十三天| LeetCode1049.最后一块石头的重量 II、LeetCode494.目标和、LeetCode474.一和零

本文解析了LeetCode中的三个问题,涉及背包问题的动态规划解决方案,包括1049、494和474号题目,通过实例展示了如何定义dp数组、初始化、递推公式以及遍历顺序,以求解背包的最大重量或物品组合种类。
摘要由CSDN通过智能技术生成

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

题目链接:1049. 最后一块石头的重量 II - 力扣(LeetCode)

【解题思路】

  • 尽量让两堆石头的重量相同,让留下的石头重量最小,这样,本题就可以抽象成01背包问题

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

    • dp[j]的定义为:装满容量为j的背包最大重量为dp[j]

  • 3.确定dp数组如何初始化

    • dp[0]=0

      • 意思是背包容量为0的时候,背包重量为0

    • 非零下标应该初始化为非负数里的最小值,因为我们需要不断地进行比较,取最大值更新

  • 5.举例推导dp数组

    • 手动推导一下答案,然后将数组打印出来,看看每个状态是否是按照我们的思路进行转移的

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

    • 因为重量和价值都是nums[i]

  • 两层for循环:

    • 第一层遍历物品:

      • 第二层遍历背包容量:

        • 递推公式

  • 注意:因为一维数组每一层的数据是需要重复利用的,因此遍历顺序只能是倒序遍历

    • 我们需要倒序来保证每个物品添加一次,因为需要保证每个物品只添加一次,所以必须先遍历物品,再遍历背包

【解题步骤】

  • 1.定义一个sum,统计当前数组总数

  • 2.target = sum/2

  • 3.初始化dp数组,大小为target+1

  • 4.先遍历物品:

    • 再遍历背包:

      • 递推公式

  • 5.返回 sum - 2*dp[target]

LeetCode 494 目标和

题目链接:494. 目标和 - 力扣(LeetCode)

【解题思路】

  • 根据题意,假设加法的总和为x,那么减法对应的集合就是sum-x

    • 因此我们要求的是x-(sum-x) = target

    • 可以写成x = (target+sum)/2

  • 因此本题就是给我们一个背包的容量,问我们有多少种方式能把这个背包装满

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

    • dp[j]的定义为:装满容量为j的背包有dp[j]种方法

  • 2.确定递推公式

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

  • 3.确定dp数组如何初始化

    • dp[0]=1

      • 意思装满容量为0的背包,有1种方法

    • 因为我们当前下标的值是由前一个下标的值累加而成,因此不能将dp[0]初始化为0

  • 4.确定遍历顺序

    • 两层for循环:

      • 第一层遍历物品:

        • 第二层遍历背包容量:

          • 递推公式

    • 注意:因为一维数组每一层的数据是需要重复利用的,因此遍历顺序只能是倒序遍历

      • 我们需要倒序来保证每个物品添加一次,因为需要保证每个物品只添加一次,所以必须先遍历物品,再遍历背包

  • 5.举例推导dp数组

    • 手动推导一下答案,然后将数组打印出来,看看每个状态是否是按照我们的思路进行转移的

【解题步骤】

  • 1.定义一个sum,统计当前数组总数

  • 2.如果target的绝对值大于sum,直接return 0;

  • 3.如果target + sum除以2的余数不为0,直接return0;

  • 4.背包容量 = (target+sum)/2

  • 5.创建dp数组,初始化大小为背包长度+1

  • 6.初始化dp[0] = 1

  • 4.先遍历物品:

    • 再遍历背包:

      • 递推公式

  • 5.返回dp[bagtargeyt]

LeetCode 474 一和零

题目链接:474. 一和零 - 力扣(LeetCode)

【解题思路】

  • 本题求的是装满这个背包最多有多少种物品

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

    • dp[i][j]的定义为:装满i个0,j个1的背包最多有多少种物品

    • 最终要求的结果是dp[m][n]

  • 2.确定递推公式

    • 首先需要明确:

      • 物品的重量为:多少个0和多少个1

      • 背包的容量为:题目给出的m个0和n个1

    • dp[i][j] = max(dp[i][j],dp[i-x][j-y]+1)

  • 3.确定dp数组如何初始化

    • dp[0][0]=0

      • 意思背包容量为0时我们所装的物品种类数量为0

    • 非零下标应该也初始成0,为了避免覆盖掉后面结果

  • 4.确定遍历顺序

    • 两层for循环:

      • 第一层遍历物品(遍历字符串集合里的每一个字符串):

        • 遍历字符串中的每一个字符:

          • 将当前物品包含有多少个1,多少个0统计出来,也就是记录当前物品的重量

        • 第二层遍历背包容量:

          • 用两个for循环,遍历当前物品的0和1的个数

          • 递推公式

    • 注意:因为一维数组每一层的数据是需要重复利用的,因此遍历顺序只能是倒序遍历

      • 我们需要倒序来保证每个物品添加一次,因为需要保证每个物品只添加一次,所以必须先遍历物品,再遍历背包

  • 5.举例推导dp数组

    • 手动推导一下答案,然后将数组打印出来,看看每个状态是否是按照我们的思路进行转移的

【解题步骤】

  • 1.定义二维dp数组,大小初始化为m+1和n+1

  • 2.定义x,y记录当前物品的01数量

  • 3.遍历字符串数组(遍历物品):

    • 1)将x,y初始化为0

      • 目的是在每取出一个字符串时,都将xy计数器归0,重新统计0,1的个数

    • 2)遍历当前字符串:

      • 如果当前字符为0,则x++

      • 如果当前字符为1,则y++

    • 3)从i->x,遍历当前背包中0的数量:

      • 从j->y,遍历当前背包中1的数量:

        • 递推公式

  • 4.返回dp[m][n]

  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值