背包问题总结

参考1
参考2

什么是背包问题

背包问题是一类经典的动态规划问题,它非常灵活。

背包问题的特征: 一般有个target,求组成target的组合方式等等

分类: 0-1背包问题、完全背包问题
0-1背包问题:数组中的元素不能重用,外层遍历数组,内层逆序遍历target。
完全背包问题:数组中的元素可以重复使用

  • 不考虑数组的顺序,外层遍历数组,内层顺序遍历target
  • 考虑数组的顺序,外层遍历target,内层遍历数组

leetcode494:目标和

0-1背包问题

给你一个整数数组 nums 和一个整数 target 。
向数组中的每个整数前添加 '+' 或 '-' ,然后串联起所有整数,可以构造一个 表达式 :
例如,nums = [2, 1] ,可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1" 。
返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 
class Solution:
    def findTargetSumWays(self, nums: List[int], target: int) -> int:
        sum_n = sum(nums)
        neg = (sum_n - target) % 2
        if neg or sum_n < target:
            return 0
        target = (sum_n - target) // 2
        dp = [0] * (target+1)
        dp[0] = 1
        for num in nums:
            for i in range(target, num-1, -1):
                dp[i] = dp[i-num] + dp[i]
        return dp[-1]

leetcode518

完全背包问题

给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。
请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。
#完全背包问题
class Solution(object):
    def change(self, amount, coins):
        """
        :type amount: int
        :type coins: List[int]
        :rtype: int
        """
        dp = [0] * (amount+1)
        dp[0] = 1
        for coin in coins:
            for j in range(coin, amount+1):
                dp[j] = dp[j] + dp[j-coin]
        return dp[-1]

leetcode322. 零钱兑换

完全背包问题

给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
你可以认为每种硬币的数量是无限的
#完全背包问题
class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        n = len(coins)
        dp = [float("inf")] * (amount+1)
        dp[0] = 0       #dp表示填满i的背包最少需要多少coin
        for coin in coins:
            for i in range(coin, amount+1):
                dp[i] = min(dp[i], dp[i-coin]+1)
        return dp[-1] if dp[-1] != float("inf") else -1

416. 分割等和子集

0-1背包问题:

给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
#0-1背包问题
class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        sum_n = sum(nums)
        if sum_n % 2:
            return False
        target = sum_n // 2
        dp = [False] * (target+1)
        dp[0] = True
        for num in nums:
            for i in range(target, num-1, -1):
                dp[i] = dp[i] or dp[i-num]
        return dp[-1]

377. 组合总和 Ⅳ

这道题考虑顺序

给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。
#这道题考虑顺序
class Solution(object):
    def combinationSum4(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        n = len(nums)
        dp = [0] * (target+1)
        dp[0] = 1
        for i in range(target+1):
            for num in nums:
                if num <= i:
                    dp[i] = dp[i] + dp[i-num]
        return dp[-1]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值