从零学算法62

文章讨论了一个机器人从网格左上角到达右下角的不同路径数量问题。给出了两种方法,一种是超时的递归解决方案,另一种是使用动态规划优化后的解决方案,通过添加额外的行和列来处理边界条件。动态规划方法避免了重复计算,提高了效率。
摘要由CSDN通过智能技术生成

62.一个机器人位于一个 m x n 网格的左上角 。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角。
问总共有多少条不同的路径?
示例 1:
输入:m = 3, n = 7
输出:28
示例 2:
输入:m = 3, n = 2
输出:3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右
3. 向下 -> 向右 -> 向下

  • 做不出来,只有超时解法:直接递归,从终点 (m,n) 到起点 (1,1) 和最终结果一样。
  •   public int uniquePaths(int m, int n) {
      	// 走到起点说明当前路径可行
          if(m == 1 && n == 1){
              return 1;
          }
          // 走得超出边界了说明路径不可行
          if(m < 1 || n < 1){
              return 0;
          }
          // 递归往右一步或者往下一步是否可行
          return uniquePaths(m-1,n) + uniquePaths(m,n-1);
      }
    
  • 题号:62
  • 他人解法:首先定义 f[i][j] 为到达位置 (i,j) 的不同路径数量。从终点 f[m-1][n-1] 来看,由于只能往下或者往右走,所以到达终点前的位置只有两种可能,也就是他的左边或者上面,即 f[m-2][n-1] 和 f[m-1][n-2],继续推断,那么可以得到 f[i][j] = f[i-1][j] + f[i][j-1],但是有个问题,如果你已经贴着上墙了,你还可能是从上面和左边过来的吗,很明显不是,这时你只有可能是从左边来到这个点,也就是此时 f[i][j] = f[i-1][j],同理如果已经贴着左墙了,肯定是从上面来的。
  •   public int uniquePaths(int m, int n) {
          int[][] f = new int[m][n];
          f[0][0] = 1;
          // i 表示行,所以表示上下移动,j 表示列,所以表示左右移动
          for (int i = 0; i < m; i++) {
              for (int j = 0; j < n; j++) {
                  if (i > 0 && j > 0) {
                      f[i][j] = f[i - 1][j] + f[i][j - 1];
                  } else if (i > 0) {
                  	// 此时说明 j==0,也就是在第 0 行列,等于贴着左墙了
                  	// 只能往下移动,说明他和上一个位置相同
                      f[i][j] = f[i - 1][j];
                  } else if (j > 0) {
                  	// 此时说明 i==0,和 j==0 同理
                      f[i][j] = f[i][j - 1];
                  }
              }
          }
          return f[m - 1][n - 1];
      }
    
  • 也可以修改一下,增加一行和一列,然后起点就改为 (0,1) 或 (1,0),这时那种从墙壁外过来的下标,值都是 0,就不需要考虑贴墙的情况了
  •   public int uniquePaths(int m, int n) {
          int[][] f = new int[m+1][n+1];
          f[1][0] = 1;
          for (int i = 1; i <= m; i++) {
              for (int j = 1; j <= n; j++) {
                  f[i][j] = f[i - 1][j] + f[i][j - 1];
              }
          }
          return f[m][n];
      }
    
  • 参考链接
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值