不同路径

169 阅读3分钟

「这是我参与2022首次更文挑战的第26天,活动详情查看:2022首次更文挑战

前言

笔者除了大学时期选修过《算法设计与分析》和《数据结构》还是浑浑噩噩度过的(当时觉得和编程没多大关系),其他时间对算法接触也比较少,但是随着开发时间变长对一些底层代码/处理机制有所接触越发觉得算法的重要性,所以决定开始系统的学习(主要是刷力扣上的题目)和整理,也希望还没开始学习的人尽早开始。

系列文章收录《算法》专栏中。

力扣题目链接

问题描述

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?

示例 1:

image.png

输入:m = 3, n = 7
输出:28

示例 2:

输入:m = 3, n = 2
输出:3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右
3. 向下 -> 向右 -> 向下

示例 3:

输入:m = 7, n = 3
输出:28

示例 4:

输入:m = 3, n = 3
输出:6

 

提示:

  • 1 <= m, n <= 100
  • 题目数据保证答案小于等于 2 * 10^9

剖析

这道题用到了动态规划,可以用f(i,j)表示从左上角走到(i,j)的路径数量,i为题目的m,j为题目的n,因为机器人已经在左上角的第一个格子中,所以其实相当于已经在(1,1)上,所以结果为f(m-1,n-1)。

那么怎么求f(m-1,n-1)表示的路径是多少呢?

  • 我们先看下比较特殊的,到最上面一行或者到最右边一列的路径是不是不管哪一格都是为1?那么我们就可以得出f(0,j)=1和f(i,0)=1。
  • 如果我们向下走一步会从(i-1,j)走过来,如果我们向右走一步会从(i,j-1)走过来,所以可以得出动态规划转移方程:f(i,j)=f(i-1,j)+f(i,j-1)。
  • 我们可以发现要求出f(i,j)只要求出它走到上面格子的路径f(i-1,j)和走到左边格子路径f(i,j-1之和就行了。我们可以试下,比如m=2 n=2,f(1,1)=f(0,1)+f(1,0)=2,再比如m=3 n=2,f(2,1)=f(1,1)+f(2,0)=3。

解这道题给我的感觉很像递归:求出外层的东西需要先到内层,先分后总。然后加上特殊边界值进而归纳总结出的结果。

所以代码如下

代码

public int uniquePaths(int m, int n) {
    int[][] f = new int[m][n];
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (i == 0) {
                f[i][j] = 1;
                continue;
            }
            if (j == 0) {
                f[i][j] = 1;
                continue;
            }
            f[i][j] = f[i - 1][j] + f[i][j - 1];
        }
    }
    return f[m - 1][n - 1];
}