算法训练 Day 44

LeetCode 518. 零钱兑换 II

题目链接:518. 零钱兑换 II

思路:分析本题的动规五部曲:

  1. 确定dp数组及其下标的含义
    dp[j]:凑成金额数为 j 的货币组合数为dp[j]
  2. 确定递推公式
    dp[j] 就是所有的dp[j - coins[i]]相加,所以递推公式为: d p [ j ] + = d p [ j − c o i n s [ i ] ] dp[j] += dp[j - coins[i]] dp[j]+=dp[jcoins[i]]
  3. 初始化dp数组
    dp[0] = 1,可以理解为凑成0元金额的组合数为1种
  4. 确定遍历顺序
    回看一下dp数组的定义,是凑成金额数为 j 的组合数,也就是说从金额开始遍历数组中的每个货币,把这句话翻译一下就是,先遍历货币(物品)、再遍历金额(背包容量)。
  5. 打印dp数组结果

Python版本:

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

        return dp[-1]

时间复杂度: O ( n ∗ a m o u n t ) O(n * amount) O(namount),空间复杂度: O ( a m o u n t ) O(amount) O(amount)

go版本:

func change(amount int, coins []int) int {
    dp := make([]int, amount+1)
    dp[0] = 1

    for i:=0; i<len(coins); i++ {
        for j:=coins[i]; j<amount+1; j++ {
            dp[j] += dp[j-coins[i]]
        }
    }
    return dp[amount]
}

LeetCode 377. 组合总和 Ⅳ

题目链接:377. 组合总和 Ⅳ

思路:分析本题的动规五部曲:

  1. 确定dp数组及其下标的含义
    dp[j]:和为 j 的组合数为dp[j]
  2. 确定递推公式
    dp[j] 就是所有的dp[j - nums[i]]相加,所以递推公式为: d p [ j ] + = d p [ j − n u m s [ i ] ] dp[j] += dp[j - nums[i]] dp[j]+=dp[jnums[i]]
  3. 初始化dp数组
    dp[0] = 1,可以理解为和为0的组合数为1种
  4. 确定遍历顺序
    回看一下dp数组的定义,是和为 j 的组合数,而这道题与上一题的区别就在于:上一题排列不强调顺序,而本题不同的排列顺序是另一种组合。所以本题要先遍历背包容量,在内循环里遍历物品。
    我们总结出一个规律:如果题目的排列不强调顺序,那应该先遍历物品,再遍历背包容量;如果题目的排列强调顺序(不同的排列顺序表示不同的结果),那应该先遍历背包容量,再遍历物品。
  5. 打印dp数组结果

Python版本:

class Solution:
    def combinationSum4(self, nums: List[int], target: int) -> int:
        dp = [0]*(target+1)
        dp[0] = 1

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

        return dp[target]

时间复杂度: O ( n ∗ t a r g e t ) O(n * target) O(ntarget),空间复杂度: O ( t a r g e t ) O(target) O(target)

go版本:

func combinationSum4(nums []int, target int) int {
    dp := make([]int, target+1)
    dp[0] = 1

    for i:=1; i<=target; i++ {
        for j:=0; j<len(nums); j++ {
            if i-nums[j]>=0 {
                dp[i] += dp[i-nums[j]]
            }
        }
    }
    return dp[target]
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值