518 零钱兑换
代码如下
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 ; j++ { 在遍历背包
dp[j] += dp[j-coins[i]] 举例 dp[3] 如果想要装满3的背包,那么就有三种可能 1+dp[2],2+dp[1],3+dp[0] ,所以总的方法是累加的
}
}
return dp[amount]
}
注 : 这里是先遍历物品,在遍历背包,所以遍历时候,会将物品1重复的放入各个背包,然后再将2重复的放入各个背包 。举例来说如果用这样的遍历方式装满背包3就有两种情况 一种是1,1,1 另一种是1,2 递推关系式分别为 dp[3] = dp[3] + dp[2] (先装满dp[2],在装入1,对应1,1,1,) dp[3] = dp[3] + dp[1] (对应的是先装满1,在装入2对应1,2,再加上之前的一种方法1,1,1所以此时dp[3]的值为2,即1,2 和1,1,1)
如果是先遍历背包在遍历物品
for j := 0 ; j <= amount ; j++ {
for i := 0 ; i < len(coins) ; i++ {
if j - coins[i] >= 0 {
dp[j] += dp[j-coins[i]]
}
}
}
还是以dp[3] 为例,那么在遍历dp[3]之前会完成dp[2]的遍历dp[2]为2 即1,1 和 2 两种情况
此时dp[3] = dp[3] + dp[2] 这个表达式说明此时要放入1 ,是在dp[2]基础上的,即有两种情况 1,1,1,和2,1 。当要放入2时 ,dp[3] = dp[3] + dp[1] 此时又加入一种情况就是1,2 此时dp[3]的值有三种情况,即1,1,1,和2,1和1,2
377 组合总和
代码如下
func combinationSum4(nums []int, target int) int { //和上面的思路基本一致,只不过是求排列,所以先遍历背包,在遍历物品
dp := make([]int,target+1)
dp[0] = 1
for j := 0 ; j <= target ; j++ {
for i := 0 ; i < len(nums) ; i++ {
if j >= nums[i] {
dp[j] += dp[j-nums[i]]
}
}
}
return dp[target]
}
70 爬楼梯
代码如下
func climbStairs(n int) int { 思路同上,只不过是物品只要1和2
if n == 1 {
return 1
}
dp := make([]int,n+1)
m := 2
dp[0] = 1
for j := 1 ; j <= n ; j++ {
for i := 1 ; i <= m ; i++ {
if j >= i {
dp[j] += dp[j-i]
}
}
}
return dp[n]
}