算法概论week 15 | leetcode 62. Unique Paths

题目描述

在这里插入图片描述

在这里插入图片描述


解决方案

这是一个基本的DP问题。

由于机器人只能左右移动,当它到达一个点时,只有两种可能:

  • 它从上面到达这一点(向下移动到这一点);
  • 它从左到这一点(向右移动到这一点)。

因此,我们得到以下状态方程:假设到达点(i, j)的路径数记为P[i][j],则

P[i][j] = P[i - 1][j] + P[i][j - 1]

上述方程的边界条件出现在最左边的列(P[i][j - 1]不存在)和最上面的行(P[i - 1][j]不存在)。这些条件可以通过初始化(预处理)来处理——对于所有有效的i, j,初始化P[0][j] = 1, P[i][0] = 1。

现在我们可以写出以下(未优化的)代码。

class Solution {
    int uniquePaths(int m, int n) {
        vector<vector<int> > path(m, vector<int> (n, 1));
        for (int i = 1; i < m; i++)
            for (int j = 1; j < n; j++)
                path[i][j] = path[i - 1][j] + path[i][j - 1];
        return path[m - 1][n - 1];
    }
};

上述方案的时间复杂度为O(n^2),空间复杂度为O(m * n)。但是,每次更新path[i][j]时,我们只需要path[i - 1]j和path[i]j - 1。因此,我们只需要维护两列(当前列和左列),而不是维护完整的m*n矩阵。现在可以对代码进行优化,使其具有O(min(m, n))的空间复杂度。

class Solution {
    int uniquePaths(int m, int n) {
        if (m > n) return uniquePaths(n, m); 
        vector<int> pre(m, 1);
        vector<int> cur(m, 1);
        for (int j = 1; j < n; j++) {
            for (int i = 1; i < m; i++)
                cur[i] = cur[i - 1] + pre[i];
            swap(pre, cur);
        }
        return pre[m - 1];
    }
};

进一步检查上面的代码,我们发现保留两列是用来恢复pre[i]的,pre[i]在更新之前是cur[i]。所以甚至不需要使用两个向量,一个就足够了。现在进一步节省了空间,代码也变得更短了。

class Solution {
    int uniquePaths(int m, int n) {
        if (m > n) return uniquePaths(n, m);
        vector<int> cur(m, 1);
        for (int j = 1; j < n; j++)
            for (int i = 1; i < m; i++)
                cur[i] += cur[i - 1]; 
        return cur[m - 1];
    }
}; 

参考资料

0ms, 5-lines DP Solution in C++ with Explanations

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值