java实现动态规划的两种方式

java实现动态规划的两种方式

原理

  1. 动态规划简单说就是 当前结果仅依赖于几个子问题的结果

  2. 比如汉诺塔问题,把n个盘从A移动到C,仅依赖于:
    ①把n-1个盘A -->B (a步)
    ②把最后一个盘从A -->C (1步)
    ③把n-1个盘B–>C (b步)
    先得到 res=a+b+1

  3. 而其中的a,b 又可以类似res一样分别分解成子问题,(b同理)
    a=a(n-1)+b(n-1)+1
    a(n-1)=a(n-2)+b(n-2)+1

    a(2)=a(1)+b(1)+1
    此时a(1)=b(1)=1

方法一:递归

  1. 力扣算法题62,原问题如下
    在这里插入图片描述
    因为只能向下向右走,假设nums()为路径数,所以
    nums(m×n)=nums(m-1×n)+nums(m×n-1),
    是一个动态规划问题

  2. 用递归法代码结构为

class Solution 
{
   public int uniquePaths(int m, int n) 
   {
       if(m==1||n==1)
       {
           return 1;
       }
   	int right=uniquePaths(m-1,n);
   	int down=uniquePaths(m,n-1);
       return right + down
   }
}
  1. 但此方法在m×n较大时会有 运行超时异常,原因是:递归是用栈实现的,m×n较大时,栈深度增加出现栈溢出。所以需要用循环的方式去写。

方法二:循环

  1. 把上面的递归程序用循环实现,先用二维数组保存每次的结算结果
class Solution {
  public int uniquePaths(int m, int n) {
      int dp[][]=new int[m][n];
      for(int i=0;i<m;i++)
      {
          for(int j=0;j<n;j++)
          {
              if(i==0||j==0)
              {
                  dp[i][j]=1;
              }
              else
              {
                  dp[i][j]=dp[i-1][j]+dp[i][j-1];
              }
          }
      }
      return dp[m-1][n-1];
  }
}

这样就不会超时了。
2. 这时候能优化一下,因为每次只需要上一次的结果,尝试用新解覆盖旧解,就不需要m×n的数组了
3. 先观察上面代码的两层循环,i 循环一次,二维数组更新一行,直至第m行得出结果,更新的过程需要此行上一列的值上一行的值
4. 可见,不需要上上行的信息只需上行和本行的值,上行计算完后,让 上行 的值覆盖 上上行(1×n数组A),再算下一行(用1×n数组B记录)。再用B覆盖A再算下一行…迭代…所以可把m×n数组改成 2×n 的数组
5. 再进一步优化,直接在A(1×n数组)上面算下一行的值,内层循环执行完后,A就已经变成了B,省去覆盖的过程,所以只需要1×n的数组
6. 代码如下

class Solution {
   public int uniquePaths(int m, int n) {
       int dp[]=new int[n];
       for(int i=0;i<m;i++)
       {
           for(int j=0;j<n;j++)
           {
               if(i==0||j==0)
               {
                   dp[j]=1;
               }
               else
               {
                   dp[j]=dp[j]+dp[j-1];
               }
           }
       }
       return dp[n-1];
   }
}

刚开始写博客的结构有些乱,表达也很生硬。。
菜鸡也想变强,晚安return 0;

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值