leetcode509:斐波那契数
-
题目:斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:
F(0) = 0,F(1) = 1 F(n) = F(n - 1) + F(n - 2),其中 n > 1 给定 n ,请计算 F(n) 。
-
思路:斐波那契数是动态规划题目,需要解决重叠子问题
-
重叠子问题:采用备忘录进行解决,即生成一个数组,记录重叠的数据 (int dp = new int[n+1])
-
因为斐波那契数只需记录备忘录中的前两项的值,故可对其进行进一步优化
class Solution { public int fib(int n) { if(n==0||n==1){ return n; } //建立备忘录,解决动态规划的重叠子问题 int dp_i_1 = 1; int dp_i_2 = 0; for(int i =2;i<=n;i++){ //dp[n] = dp[n-1]+dp[n-2] int dp_1 = dp_i_1+dp_i_2; dp_i_2 = dp_i_1; dp_i_1 = dp_1; } return dp_i_1; } }
leetcode322:零钱兑换
-
题目:给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。你可以认为每种硬币的数量是无限的。
-
思路:解题代码有解题思路。
-
此题为一道动态规划问题,解决重复子问题和最优子结构问题。
class Solution { //准备备忘录数组 int[] dp; public int coinChange(int[] coins, int amount) { //声明并实例化备忘录数组且均赋值为-666,-666为不可能取到的金额 dp = new int[amount+1]; Arrays.fill(dp,-666); //递归函数 dp return dp(coins,amount); } public int dp(int[] coins,int amount){ //如果需要的钱数为0,则返回0 if(amount==0) return 0; //如果需要的钱数小于,则返回-1 if(amount<0) return -1; //当备忘录数组之前取过该金额的值,则直接返回原数组下标值 if(dp[amount]!=-666){ return dp[amount]; } //定义结果为最大值 int res = Integer.MAX_VALUE; //遍历 硬币数组 for(int coin: coins){ //数组coins从大到小开始遍历,amound - coin(硬币最大值)仍然大于等于0,则说明 结果+1; int subProblem = dp(coins,amount-coin); //否则,amound - coin(硬币最大值)仍然小于0,则继续遍历下个值,一直循环,直至出现结果 if(subProblem==-1) continue; res = Math.min(res,subProblem+1); } dp[amount] =(res==Integer.MAX_VALUE?-1:res) ; return dp[amount]; } }