leetcode笔记——背包问题总结2

1.找零钱的最少硬币数

322. Coin Change (Medium)

题目:

给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。

示例 1:

输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1

示例 2:

输入: coins = [2], amount = 3
输出: -1

说明:
你可以认为每种硬币的数量是无限的。

思路:

这个是一个完全背包问题。硬币的不同面值对应物品的重量,总金额对应背包的总重量,每种硬币的数量都是无限的。设数组dp[i]表示总金额为i时,最少的硬币个数。这个需要注意的是初始值的问题,因为求解的是最小值,因此数组的初值不能设置为0,在这里我们设置成了amount+1.代码参考leetcode中评论里大神的代码,如下:

代码:

class Solution {
    public int coinChange(int[] coins, int amount) {
        int dp[] = new int[amount + 1];
        Arrays.fill(dp, amount + 1);//填充数组dp,使得数组的初始值均为amount+1;
        dp[0] = 0;
  for (int i =1;i<=coins.length;i++) {
        for (int j= coins[i-1]; j <= amount;j++) {//这块注意是正序,0-1背包问题中是逆序
                
             dp[j] = Math.min(dp[j-coins[i-1]]+1,dp[j]);
                
            }
        }
        return dp[amount] > amount ? -1 : dp[amount];//如果存在和为amount的组合,此时数组元素dp[amount]的值就会发生改变
    }
}
2.找零钱的硬币组合数

  518. Coin Change 2 (Medium)

题目:

给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。

 

示例 1:

输入: amount = 5, coins = [1, 2, 5]
输出: 4
解释: 有四种方式可以凑成总金额:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1

示例 2:

输入: amount = 3, coins = [2]
输出: 0
解释: 只用面额2的硬币不能凑成总金额3。

示例 3:

输入: amount = 10, coins = [10]
输出: 1

思路:这个题也是一个完全背包问题。使用数组dp[i]表示总金额为i时,硬币的组合数,此时初始化每一个数组元素为0.但这个也好像动态规划一类的题。最后总金额为i的组合数等于不加当前的硬币时总金额就已经达到i的硬币组合数和加入当前硬币(此时的总金额数为i-硬币的面值)。

代码:

class Solution {
    public int change(int amount, int[] coins) {
       // if(coins==null||coins.length==0||amount==0) 这部分里面有一个特殊情况,就是金额为0,数组为空是结果为1。。
          //  return 0;
        int n=coins.length;
        int dp[]=new int[amount+1];
        dp[0]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=coins[i-1];j<=amount;j++)
            {
                dp[j]=dp[j]+dp[j-coins[i-1]];
            }        
        }
        return dp[amount];
    }
}

3.组合总和

377. Combination Sum IV (Medium)

题目:

给定一个由正整数组成且不存在重复数字的数组,找出和为给定目标正整数的组合的个数。

示例:

nums = [1, 2, 3]
target = 4

所有可能的组合为:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)

请注意,顺序不同的序列被视作不同的组合。

因此输出为 7。

进阶:
如果给定的数组中含有负数会怎么样?
问题会产生什么变化?
我们需要在题目中添加什么限制来允许负数的出现?

思路:是一个有顺序的完全背包问题,这个之前没有见过,补充一下.在leetcode中的讨论里面有大神说,这个一般的背包问题是物品循环在外循环,背包的重量部分在内循环;但是一旦涉及到物品顺序的问题时,只需要将背包的重量部分放在外循环,内循环是物品的循环就可以了。还要注意的是这里有一个将数组先排序的操作。

代码:

public int combinationSum4(int[] nums, int target) {
if (nums == null || nums.length == 0) {
return 0;
}
int[] maximum = new int[target + 1];
maximum[0] = 1;
Arrays.sort(nums);
for (int i = 1; i <= target; i++) {
for (int j = 0; j < nums.length && nums[j] <= i; j++) {
maximum[i] += maximum[i - nums[j]];
}
}
return maximum[target];
}

 

你可能感兴趣的:(LeetCode笔记,背包问题)