力扣算法刷题Day43|动态规划:最后一块石头的重量II 目标和 一和零

力扣题目:#1049.最后一块石头的重量II

刷题时长:5min

解题方法:动态规划

复杂度分析

  • 时间O(n^2)
  • 空间O(n)

问题总结

  • 难在如何转化题意至01背包问题

本题收获

  • 题意转换:要使相撞之后剩下的石头最小,就得凑出两堆重量最接近的石头,即01背包问题下尽量装满石头总重量一半的背包。本题物品的重量为stones[i],物品的价值也为stones[i]。
  • 动规思路:凑总重
    • 确定dp数组及下标的含义:dp[j]表示容量(这里说容量更形象,其实就是重量)为j的背包,最多可以背最大重量为dp[j]
    • 确定递推公式:dp[j] = max(dp[j], dp[j - stones[i]] + stones[i])
    • dp数组的初始化:一位数组长度为target+1,值都为0
    • 确定遍历顺序:两层for循环,第一层正序遍历石头,第二层后序遍历背包

力扣题目:#494.目标和

刷题时长:参考题解后15min

解题方法:动态规划

复杂度分析

  • 时间复杂度:O(n × m),n为正数个数,m为背包容量
  • 空间复杂度:O(m),m为背包容量

问题总结

  • 提前排除没有方案的情况,一种是正集合不为整,还有一种是abs(target) > sum(nums)
  • return错了target
  • dp[0]需初始化为1

本题收获

  • 题意转换:假设加法的总和为x,那么减法对应的总和就是sum - x。所以我们要求的是 x - (sum - x) = target,x = (target + sum) / 2。此时问题就转化为,装满容量为x的背包,有几种方法。
  • 动规思路
    • 确定dp数组及下标的含义:填满j(包括j)这么大容积的包,有dp[j]种方法
    • 确定递推公式:dp[j] += dp[j - nums[i]]
      • 只要搞到nums[i],凑成dp[j]就有dp[j - nums[i]] 种方法
    • dp数组的初始化:dp[0] = 1
    • 确定遍历顺序:外循环正序遍历nums,内循环倒序遍历target

力扣题目:#474.一和零

刷题时长:参考题解后15min

解题方法:动态规划

复杂度分析

  • 时间复杂度: O(kmn),k 为strs的长度
  • 空间复杂度: O(mn)

问题总结

  • 需要分清二维在背包上

本题收获

  • 题意转换:strs数组里每个元素即一个物品,而m和n指向背包的两个维度
  • 动规思路
    • 确定dp数组及下标的含义:最多有i个0和j个1的strs的最大子集的大小为dp[i][j]
    • 确定递推公式:dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1)
      • 字符串的zeroNum和oneNum相当于物品的重量(weight[i]),字符串本身的个数相当于物品的价值(value[i])
    • dp数组的初始化:因为物品价值不会是负数,初始为0,保证递推的时候dp[i][j]不会被初始值覆盖
    • 确定遍历顺序:外层for循环遍历物品,内层for循环遍历背包容量且从后向前遍历

你可能感兴趣的:(算法)