2022-1-25动态规划day1
题1:
509. 斐波那契数
斐波那契数,通常用 F(n)
表示,形成的序列称为 斐波那契数列 。该数列由 0
和 1
开始,后面的每一项数字都是前面两项数字的和。也就是:
F(0) = 0,F(1) = 1 F(n) = F(n - 1) + F(n - 2),其中 n > 1
给你 n
,请计算 F(n)
。
示例 1:
输入:2 输出:1 解释:F(2) = F(1) + F(0) = 1 + 0 = 1
示例 2:
输入:3 输出:2 解释:F(3) = F(2) + F(1) = 1 + 1 = 2
示例 3:
输入:4 输出:3 解释:F(4) = F(3) + F(2) = 2 + 1 = 3
提示:
0 <= n <= 30
1 class Solution { 2 public int fib(int n) { 3 int[] dp=new int[31]; 4 dp[0]=0; 5 dp[1]=1; 6 for (int i=2;i<31;i++){ 7 dp[i]=dp[i-1]+dp[i-2]; 8 } 9 return dp[n]; 10 } 11 }
思路:动态规划和递归都可以。
题2:
322. 零钱兑换
给你一个整数数组 coins
,表示不同面额的硬币;以及一个整数 amount
,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1
。
你可以认为每种硬币的数量是无限的。
示例 1:
输入:coins =[1, 2, 5]
, amount =11
输出:3
解释:11 = 5 + 5 + 1
示例 2:
输入:coins =[2]
, amount =3
输出:-1
示例 3:
输入:coins = [1], amount = 0 输出:0
示例 4:
输入:coins = [1], amount = 1 输出:1
示例 5:
输入:coins = [1], amount = 2 输出:2
提示:
1 <= coins.length <= 12
1 <= coins[i] <= 231 - 1
0 <= amount <= 104
1 class Solution { 2 public int coinChange(int[] coins, int amount) { 3 if (amount==0) return 0; 4 int[] dp=new int[amount+1]; 5 Arrays.fill(dp,Integer.MAX_VALUE/2); 6 for (int x:coins){ 7 if (x>amount) continue; 8 dp[x]=1; 9 } 10 for (int i=0;i<=amount;i++){ 11 for (int x:coins){ 12 if (icontinue; 13 dp[i]=Math.min(dp[i],dp[i-x]+1); 14 } 15 } 16 return dp[amount]==Integer.MAX_VALUE/2?-1:dp[amount]; 17 } 18 }
思路:dp[x]表示x金额花费的最少硬币,首先全部用最大值的一半代替,防止+1时溢出。遍历所有硬币,将硬币的金额全部设置为1,然后遍历数组,用每一个硬币试出最小值。
优化:
1.dp[0]应该等于0,可以省略判断第3行,以及dp[x]=1的步骤。
2.遍历金额再遍历硬币需要排除小于硬币的情况,可以反过来遍历。
1 class Solution { 2 public int coinChange(int[] coins, int amount) { 3 int[] dp=new int[amount+1]; 4 Arrays.fill(dp,Integer.MAX_VALUE/2); 5 dp[0]=0; 6 for (int x:coins){ 7 for (int i=x;i<=amount;i++){ 8 dp[i]=Math.min(dp[i],dp[i-x]+1); 9 } 10 } 11 return dp[amount]==Integer.MAX_VALUE/2?-1:dp[amount]; 12 } 13 }