代码随想录算法训练营第39天|322. 零钱兑换、279.完全平方数、139.单词拆分、多重背包

1.322. 零钱兑换

题目链接:322. 零钱兑换
文档讲解: 代码随想录

(1)确定数组和下标
dp[ j ]表示凑成总金额为 j 最少需要的硬币数
(2)递推关系式
dp[ j ] = min(dp[ j ], dp[ j - coin[ i ]] + 1)
(3)初始化
dp[0] = 0,其余位置因为会比较取最小值,初始化为’inf’
(4)遍历顺序
组合的完全背包(?),先物品后背包,都从前往后
(5)打印数组

class Solution(object):
    def coinChange(self, coins, amount):
        """
        :type coins: List[int]
        :type amount: int
        :rtype: int
        """
        dp = [float('inf')] * (amount + 1)
        dp[0] = 0
        coins.sort()
        for i in range(len(coins)):
            if coins[i] <= amount: #可以不用加这个判断条件
                for j in range(coins[i], amount + 1):
                    dp[j] = min(dp[j], dp[j - coins[i]] + 1)
        if dp[amount] == float('inf'):
            return -1
        else:
            return dp[amount]

注意点:本题是要求最少硬币数量,硬币是组合数还是排列数都无所谓!所以两个for循环先后顺序怎样都可以!但我认为这道题是求最少硬币数量,无关顺序,所以还是觉得是组合问题。

2.279.完全平方数

题目链接:279.完全平方数
文档讲解: 代码随想录

(1)确定数组和下标
dp[ j ] 表示和为 j 的最少完全平方数
(2)递推关系式
dp[ j ] = min(dp[ j ], dp[ j - i ] + 1),i 是遍历的完全平方数
(3)初始化
dp[0] = 0,其他取’inf’
(4)遍历顺序
无关顺序,按照组合完全背包,先物品后背包
(5)打印数组

class Solution(object):
    def numSquares(self, n):
        """
        :type n: int
        :rtype: int
        """
        dp = [float('inf')] * (n + 1)
        dp[0] = 0
        for i in range(1, int(n ** 0.5) + 1):
            for j in range(i * i, n + 1):
                dp[j] = min(dp[j], dp[j - i * i] + 1)
        return dp[n]

3.139.单词拆分

题目链接:139.单词拆分
文档讲解: 代码随想录

(1)确定数组和下标
dp[ i ]表示字符串长度为 i,是否可以拆分为一个或者多个在字典中出现的单词
(2)递推关系式
如果区间[j,i]区间内的子串出现在字典里并且dp[j] = True,那么dp[i] = True
(3)初始化
dp[0] = True,因为是递推的根基,否则后面都为False
(4)遍历顺序
因为单词可以重复出现,所以是完全背包问题。这道题求的是排列数,因为单词需要按照顺序排列才能组成字符串 s
(5)打印数组

class Solution(object):
    def wordBreak(self, s, wordDict):
        """
        :type s: str
        :type wordDict: List[str]
        :rtype: bool
        """
        #查找效率更高,set时间复杂度为o(1),而list为o(n)
        wordSet = set(wordDict)
        n = len(s)
        dp = [False] * (n + 1)
        dp[0] = True
        #排列,先背包后物品
        for i in range(1, n + 1):
            for j in range(i):
                if dp[j] and s[j:i] in wordSet:
                    dp[i] = True
                    break
        return dp[n]
class Solution(object):
    def wordBreak(self, s, wordDict):
        """
        :type s: str
        :type wordDict: List[str]
        :rtype: bool
        """
        dp = [False] * (len(s) + 1)
        dp[0] = True
        for j in range(1, len(s) + 1):
            for word in wordDict:
                if j >= len(word):
                    dp[j] = dp[j] or (dp[j - len(word)] and s[j - len(word): j] == word)
        return dp[len(s)]
class Solution(object):
    def wordBreak(self, s, wordDict):
        """
        :type s: str
        :type wordDict: List[str]
        :rtype: bool
        """
        #按照单词长度排序
        wordDict.sort(key = lambda x: len(x))
        dp = [False] * (len(s) + 1)
        dp[0] = True
        for j in range(1, len(s) + 1):
            for word in wordDict:
                #剪枝
                if len(word) > j:
                    break
                dp[j] = dp[j] or (dp[j - len(word)] and s[j - len(word):j] == word)
        return dp[-1]

4.多重背包

题目链接:多重背包
文档讲解: 代码随想录

C, M = [int(x) for x in input().split()]
weight = [int(x) for x in input().split()]
value = [int(x) for x in input().split()]
nums = [int(x) for x in input().split()]

dp = [0] * (C + 1)
for i in range(M):
    #背包倒序
    for j in range(C, weight[i] - 1, -1):
        for k in range(1, nums[i] + 1):
            if k * weight[i] > j:
                break
            dp[j] = max(dp[j], dp[j - k * weight[i]] + k * value[i])
print(dp[C])

卡码网一直显示超时。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值