01背包/完全背包-leetcode题目总结

Posted BJUT赵亮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了01背包/完全背包-leetcode题目总结相关的知识,希望对你有一定的参考价值。

本文记录了在学习leetcode中有关01背包/完全背包的相关问题,如果有同学在做相关内容,可以邮件(zhaoliang19960421@outlook.com)和微信(BestCoder_BestLife)和我沟通联系

在学习的过程中,学习参考了以下文档,在此表示感谢:
https://leetcode-cn.com/circle/article/lUki6J/
https://leetcode-cn.com/circle/article/KPsfIC/

leetcode相关题目

416. 分割等和子集

class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        n = len(nums)
        if n<2 or sum(nums)%2==1:
            return False
        total = sum(nums)
        maxNum = max(nums)
        target = total // 2
        if maxNum > target:
            return False
        
        # 2维
        dp = [[False] * (target + 1) for _ in range(n)]
        for i in range(n):
            dp[i][0] = True # 一个物品都不选时,一定可以满足容量为0
        dp[0][nums[0]] = True #
        for i in range(1, n):
            num = nums[i]
            for j in range(1, target + 1):
                if j >= num:
                    dp[i][j] = dp[i - 1][j] or dp[i - 1][j - num]
                else:
                    dp[i][j] = dp[i - 1][j]
        return dp[n - 1][target]

        # 1维
        dp = [False for i in range(target+1)]
        dp[nums[0]] = True
        for i in range(1,n):
            for j in range(target,0,-1):
                if j >= nums[i]:
                    dp[j] = dp[j-nums[i]] or dp[j]
        return dp[target] 

494. 目标和

class Solution:
    def findTargetSumWays(self, nums: List[int], target: int) -> int:
        sums = sum(nums)
        if sums < abs(target) or (sums + target) % 2:
            return 0
        target = (sums + target) // 2
        n = len(nums)

        # dp = [[0] * (target + 1) for _ in range(n + 1)]
        # for i in range(n + 1):
        #     dp[i][0] = 1
        # for i in range(1, n + 1):
        #     for j in range(target + 1):
        #         num = nums[i - 1]
        #         if j < num:
        #             dp[i][j] = dp[i - 1][j]
        #         else:
        #             dp[i][j] = dp[i - 1][j] + dp[i - 1][j - num]
        # return dp[-1][-1]

        dp = [0]*(target+1)
        dp[0] = 1
        for i in range(n):
            for j in range(target,-1,-1):
                if j >= nums[i]:
                    dp[j] = dp[j] + dp[j-nums[i]]
        return dp[target]

474. 一和零

class Solution:
    def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
        Len = len(strs)
        # 记录下三维数组的写法,外层遍历必须用for _ in range()的方式申请内存,不能用[]*n浅拷贝的方式申请
        dp = [[[0 for _ in range(n + 1)] for _ in  range(m + 1)] for _ in range(Len)]
        for k in range(0, Len):
            cnt0 = strs[k].count('0')
            cnt1 = strs[k].count('1')
            for i in range(m + 1):
                for j in range(n + 1):
                    dp[k][i][j] = dp[k-1][i][j]             
                    if i - cnt0 >= 0 and j - cnt1 >= 0:    
                        dp[k][i][j] = max(dp[k][i][j], dp[k-1][i-cnt0][j-cnt1] + 1)
        return min(dp[Len-1][m][n],len(strs))

322. 零钱兑换

class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        m = len(coins)
        # dp = [[1e5]*(amount+1) for _ in range(m+1)]
        # for i in range(m+1):
        #     dp[i][0] = 0
        # for i in range(1,m+1):
        #     c = coins[i-1]
        #     for j in range(1,amount+1):
        #         if j >=c:
        #             dp[i][j] = min(dp[i-1][j],dp[i][j-c]+1)
        #         else:
        #             dp[i][j] = dp[i-1][j]
        # if dp[m][amount] == 1e5:return -1
        # return dp[-1][-1]


        dp = [1e5]*(amount+1)
        dp[0] = 0
        for i in range(m):
            for j in range(1,amount+1):
                if j>=coins[i]:
                    dp[j] = min(dp[j-coins[i]]+1,dp[j])
        if dp[amount] == 1e5:return -1
        return dp[amount]

518. 零钱兑换 II

class Solution:
    def change(self, amount: int, coins: List[int]) -> int:
        m = len(coins)
        # dp = [[0]*(amount+1) for _ in range(m+1)]
        # for i in range(m+1):
        #     dp[i][0] = 1
        # for i in range(1,m+1):
        #     c = coins[i-1]
        #     for j in range(1,amount+1):
        #         if j >= c:
        #             dp[i][j] = dp[i-1][j] + dp[i][j-c]
        #         else:
        #             dp[i][j] = dp[i-1][j]
        # return dp[m][amount]  

        dp = [0] * (amount+1)
        dp[0] = 1
        for i in range(m):
            for j in range(amount+1):
                c = coins[i]
                if j>=c:
                    dp[j] = dp[j] + dp[j-c]
        return dp[amount]

01背包: 879. 盈利计划 1049. 最后一块石头的重量 II 1230. 抛掷硬币

完全背包:1449. 数位成本和为目标值的最大数字 518. 零钱兑换 II 279. 完全平方数

https://leetcode-cn.com/problems/target-sum/solution/mu-biao-he-by-leetcode-solution-o0cp/

https://leetcode-cn.com/problems/target-sum/solution/494-mu-biao-he-dong-tai-gui-hua-zhi-01be-78ll/
https://leetcode-cn.com/problems/last-stone-weight-ii/solution/yi-pian-wen-zhang-chi-tou-bei-bao-wen-ti-5lfv/
https://leetcode-cn.com/problems/combination-sum-iv/solution/xi-wang-yong-yi-chong-gui-lu-gao-ding-bei-bao-wen-/
大家在公众号里学习回溯算法专题的时候,一定做过这两道题目回溯算法:39.组合总和和回溯算法:40.组合总和II会感觉这两题和本题很像!
https://leetcode-cn.com/problems/combination-sum-iv/solution/dai-ma-sui-xiang-lu-377-zu-he-zong-he-iv-pj9s/
https://leetcode-cn.com/problems/combination-sum-iv/solution/yi-tao-kuang-jia-jie-jue-bei-bao-wen-ti-q0zxb/

以上是关于01背包/完全背包-leetcode题目总结的主要内容,如果未能解决你的问题,请参考以下文章

Java 求解零钱兑换

[M背包] lc279. 完全平方数(完全背包)

01背包问题总结

01背包问题总结

leetcode 518. 零钱兑换 II-----完全背包套路模板

518. 零钱兑换 II(完全背包一维二维的理解)