2025-2-27-4.10 动态规划(0-1 背包问题)

文章目录

4.10 动态规划(0-1 背包问题)

0-1 背包问题,现在有点明了了,以前只觉得高大上,现在看来就是一个固定的模型思路,体积有限,物品有限,获取在固定体积下能得到的最大的物品价值。

原视频讲解链接

494. 目标和

题目链接

给你一个非负整数数组 nums 和一个整数 target 。

向数组中的每个整数前添加 '+' 或 '-' ,然后串联起所有整数,可以构造一个 表达式 :

例如,nums = [2, 1] ,可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1" 。

返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

示例 1:

输入:nums = [1,1,1,1,1], target = 3

输出:5

解释:一共有 5 种方法让最终目标和为 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

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

示例 2:

输入:nums = [1], target = 1

输出:1

提示:

  • 1 <= nums.length <= 20
  • 0 <= nums[i] <= 1000
  • 0 <= sum(nums[i]) <= 1000
  • -1000 <= target <= 1000

题目解析:有一定的数学推导,具体看灵神的题解,不难理解。

方法一:递归

python 复制代码
class Solution:
    def findTargetSumWays(self, nums: List[int], target: int) -> int:

        """
        方法一:递归
        时间复杂度:O(nm),其中 n 为 nums 的长度,m 为 nums 的元素和减去 target 的绝对值。
            由于每个状态只会计算一次,动态规划的时间复杂度 = 状态个数 × 单个状态的计算时间。
            本题状态个数等于 O(nm),单个状态的计算时间为 O(1),所以动态规划的时间复杂度为 O(nm)。
        空间复杂度:O(nm)。保存多少状态,就需要多少空间。
        """

        s = sum(nums) - abs(target)
        if s < 0 or s % 2:
            return 0
        m = s // 2

        @cache #缓存装饰器,避免重复计算 dfs 的结果
        def dfs(i: int, c: int) -> int:
            if i < 0:
                return 1 if c == 0 else 0
            if c < nums[i]:
                return dfs(i - 1, c)
            return dfs(i - 1, c) + dfs(i - 1, c - nums[i]) # 不选 + 选
        
        return dfs(len(nums) - 1, m)
        

方法二:递推

python 复制代码
class Solution:
    def findTargetSumWays(self, nums: List[int], target: int) -> int:

        """
        方法二:递推
        时间复杂度:O(nm),
            其中 n 为 nums 的长度,
            m 为 nums 的元素和减去 target 的绝对值。
        空间复杂度:O(nm)。保存多少状态,就需要多少空间。
        """

        s = sum(nums) - abs(target)
        if s < 0 or s % 2:
            return 0
        m = s // 2
        n = len(nums)

        f = [[0] * (m + 1) for _ in range(n+1)]
        f[0][0] = 1

        for i, x in enumerate(nums):
            for c in range(m+1):
                if c < x:
                    f[i + 1][c] = f[i][c]
                else:
                    f[i + 1][c] = f[i][c] + f[i][c - x]
        return f[n][m]
        

方法三:递推+滚动数组

python 复制代码
class Solution:
    def findTargetSumWays(self, nums: List[int], target: int) -> int:


       
        """
        方法三:递推+滚动数组
        时间复杂度:O(nm),
            其中 n 为 nums 的长度,
            m 为 nums 的元素和减去 target 的绝对值。
        空间复杂度:O(m)。保存多少状态,就需要多少空间。
        """

        s = sum(nums) - abs(target)
        if s < 0 or s % 2:
            return 0
        m = s // 2
        n = len(nums)

        f = [[0] * (m + 1) for _ in range(2)]
        f[0][0] = 1

        for i, x in enumerate(nums):
            for c in range(m+1):
                if c < x:
                    f[(i + 1)%2][c] = f[i%2][c]
                else:
                    f[(i + 1)%2][c] = f[i%2][c] + f[i%2][c - x]
        return f[n%2][m]
 

方法四:递推+单个数组

python 复制代码
class Solution:
    def findTargetSumWays(self, nums: List[int], target: int) -> int:

        """
        方法四:递推+简化数组
        时间复杂度:O(nm),
            其中 n 为 nums 的长度,
            m 为 nums 的元素和减去 target 的绝对值。
        空间复杂度:O(m)。保存多少状态,就需要多少空间。
        """

        s = sum(nums) - abs(target)
        if s < 0 or s % 2:
            return 0
        m = s // 2
        n = len(nums)

        f = [1] + [0] * m

        for x in nums:
            for c in range(m,x-1,-1):
                    f[c] += f[c - x]
        return f[m]
相关推荐
CoderYanger21 分钟前
C.滑动窗口-求子数组个数-越长越合法——2799. 统计完全子数组的数目
java·c语言·开发语言·数据结构·算法·leetcode·职场和发展
C++业余爱好者25 分钟前
Java 提供了8种基本数据类型及封装类型介绍
java·开发语言·python
厕所博士25 分钟前
红黑树原理前置理解—— 2-3 树
算法·2-3树·红黑树原理理解前置
萌>__<新1 小时前
力扣打卡每日一题————除自身外所有元素的乘积
数据结构·算法
AI Echoes1 小时前
构建一个LangChain RAG应用
数据库·python·langchain·prompt·agent
xu_yule1 小时前
算法基础—搜索(2)【记忆化搜索+BFS+01BFS+Floodfill]
数据结构·算法
s09071362 小时前
Xilinx FPGA使用 FIR IP 核做匹配滤波时如何减少DSP使用量
算法·fpga开发·xilinx·ip core·fir滤波
老马啸西风2 小时前
成熟企业级技术平台-10-跳板机 / 堡垒机(Bastion Host)详解
人工智能·深度学习·算法·职场和发展
子夜江寒2 小时前
逻辑回归简介
算法·机器学习·逻辑回归
软件算法开发2 小时前
基于ACO蚁群优化算法的多车辆含时间窗VRPTW问题求解matlab仿真
算法·matlab·aco·vrptw·蚁群优化·多车辆·时间窗