java 动态规划算法
斐波那契数列
暴力解法
class Solution {
//暴力递归解法
public int fib(int n) {
//base case
if(n==0||n==1) return n;
return fib(n-1)+fib(n-2);
}
}
递归算法的时间复杂度=递归的次数x递归函数本身的时间复杂度
带备忘录的递归算法
class Solution {
//带备忘录的递归算法
public int fib(int n) {
//备忘录全部初始化为0
int [] memo=new int [n+1];
//进行备忘录的递归
return helper(memo,n);
}
private int helper(int []memo,int n){
//base case
if(n==0||n==1){
return n;
}
//已经记录过就不用在计算了
if(memo[n]!=0){
return memo[n];
}
memo[n]=(helper(memo,n-1)+helper(memo,n-2))%1000000007;
return memo[n];
}
}
自底向上的dp数组迭代解法
class Solution {
//自底向上的递归数组迭代dp法
public int fib(int n) {
if(n==0||n==1) return n;
int []dp =new int [n+1];
//base case
dp[0]=0;dp[1]=1;
//状态转移
for(int i=2;i<=n;i++){
dp[i]=(dp[i-1]+dp[i-2])%1000000007;
}
return dp[n];
}
}
优化空间复杂度
class Solution {
//优化空间复杂度
public int fib(int n) {
//base case
if(n==0||n==1) return n;
int pre=0,curr=1;
int sum;
for(int i=2;i<=n;i++){
sum=(pre+curr)%1000000007;
pre=curr;
curr=sum;
}
return curr;
}
}
零钱兑换问题
暴力递归算法
class Solution {
//暴力递归解法
//状态:目标金额amount
//选择:coins数组中列出的所有硬币面额
//函数的定义:凑出总金额amount,至少需要coinChage(coins,amount)枚硬币
//base case:amount<0时不可能凑出,amount==0时需要0枚硬币
public int coinChange(int[] coins, int amount) {
//base case
if(amount==0) return 0;
if(amount<0) return -1;
int res=Integer.Max_VALUE;
for(int coin: coins){
//计算子问题的结果
int subRes=coinChange(coins,amount-coin);
if(subRes==-1) continue;
//在子问题中选择最优解,然后加1
res=Math.min(res,subRes+1);
}
return res==Integer.Max_VALUE?-1:res;
}
}
自顶向下递归–备忘录解法
class Solution {
//备忘录
//状态:目标金额amount
//选择:coins数组中列出的所有硬币面额
//函数的定义:凑出总金额amount,至少需要coinChage(coins,amount)枚硬币
//base case:amount<0时不可能凑出,amount==0时需要0枚硬币
int []memo;
public int coinChange(int[] coins, int amount) {
memo=new int [amount+1];
//memo数组全部初始化为特殊值
Arrays.fill(memo,-666);
return dp(coins ,amount);
}
private int dp(int [] coins,int amount){
//base case
if(amount==0) return 0;
if(amount<0) return -1;
//查备忘录,防止重复计算
if(memo[amount]!=-666){
return memo[amount];
}
int res=Integer.MAX_VALUE;
for(int coin:coins){
//计算子问题的结果
int subRes=dp(coins,amount-coin);
if(subRes==-1) continue;
res=Math.min(res,subRes+1);
}
//把计算结果存入备忘录中
memo[amount]=(res==Integer.MAX_VALUE?-1:res);
return memo[amount];
}
}
自底向上的迭代解法
class Solution {
//自底向上的迭代解法
public int coinChange(int[] coins, int amount) {
int []dp=new int [amount+1];
//dp数组全部初始化为特殊值
Arrays.fill(dp,amount+1);
//base case
dp[0]=0;
//外层for循环遍历所有状态的取值
for(int i=0;i<dp.length;i++){
for(int coin : coins){
//子问题无解跳过
if(i-coin<0) continue;
//状态转移
dp[i]=Math.min(dp[i],1+dp[i-coin]);
}
}
//
return (dp[amount]==amount+1)?-1:dp[amount];
}
}