算法练习Day30 (Leetcode/Python-动态规划)

发布时间:2024年01月17日

62. Unique Paths

There is a robot on an?m x n?grid. The robot is initially located at the?top-left corner?(i.e.,?grid[0][0]). The robot tries to move to the?bottom-right corner?(i.e.,?grid[m - 1][n - 1]). The robot can only move either down or right at any point in time.

Given the two integers?m?and?n, return?the number of possible unique paths that the robot can take to reach the bottom-right corner.

思路:以下分析摘自https://programmercarl.com/0062.%E4%B8%8D%E5%90%8C%E8%B7%AF%E5%BE%84.html#%E6%80%9D%E8%B7%AF

树的深度是m+n+1,二叉树的节点个数是2^(m+n+1),DFS需要遍历整个二叉树,算法复杂度就是O(2^(m + n - 1) - 1),这是指数级别的复杂度。

机器人从(0 , 0) 位置出发,到(m - 1, n - 1)终点。

按照动规五部曲来分析:

1. 确定dp数组(dp table)以及下标的含义

dp[i][j] :表示从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路径。

2. 确定递推公式

想要求dp[i][j],只能有两个方向来推导出来,即dp[i - 1][j] 和 dp[i][j - 1]。

此时在回顾一下 dp[i - 1][j] 表示啥,是从(0, 0)的位置到(i - 1, j)有几条路径,dp[i][j - 1]同理。

那么很自然,dp[i][j] = dp[i - 1][j] + dp[i][j - 1],因为dp[i][j]只有这两个方向过来。

3. dp数组的初始化

如何初始化呢,首先dp[i][0]一定都是1,因为从(0, 0)的位置到(i, 0)的路径只有一条,那么dp[0][j]也同理。

4. 确定遍历顺序

这里要看一下递推公式dp[i][j] = dp[i - 1][j] + dp[i][j - 1],dp[i][j]都是从其上方和左方推导而来,那么从左到右一层一层遍历就可以了。

这样就可以保证推导dp[i][j]的时候,dp[i - 1][j] 和 dp[i][j - 1]一定是有数值的。

5. 举例推导dp数组

数论方法:

可以看出一共m,n的话,无论怎么走,走到终点都需要 m + n - 2 步。

在这m + n - 2 步中,一定有 m - 1 步是要向下走的,不用管什么时候向下走。

那么有几种走法呢? 可以转化为,给你m + n - 2个不同的数,随便取m - 1个数,有几种取法。

那么这就是一个组合问题了。

所以以下就是可走的path的个数:

递归法:

def Solution():
    def uniquePaths(self, m, n):
        if m == 1 or n == 1:
            return 1
        return self.uniquePaths(m - 1, n) + self.uniquePaths(m, n-1)

动态规划法:

class Solution(object):
    def uniquePaths(self, m, n):
        dp = [[0] * n] * m
        for i in range(m):
            dp[i][0] = 1
        for j in range(n):
            dp[0][j] = 1
        for i in range(1,m):
            for j in range(1,n):
                dp[i][j] = dp[i-1][j] + dp[i][j-1]
        return dp[m-1][n-1]

注意!之前习惯了numpy,总是直接dp[:,0] = 1,这样在list里是不对的。

63. Unique Paths II

如果有障碍物的话,之后的路就不通了,在设置初始状态和更新状态的时候都要对应改动。

具体分析见此链接代码随想录

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        if (obstacleGrid[0][0] == 1)
            return 0;
        vector<int> dp(obstacleGrid[0].size());
        for (int j = 0; j < dp.size(); ++j)
            if (obstacleGrid[0][j] == 1)
                dp[j] = 0;
            else if (j == 0)
                dp[j] = 1;
            else
                dp[j] = dp[j-1];

        for (int i = 1; i < obstacleGrid.size(); ++i)
            for (int j = 0; j < dp.size(); ++j){
                if (obstacleGrid[i][j] == 1)
                    dp[j] = 0;
                else if (j != 0)
                    dp[j] = dp[j] + dp[j-1];
            }
        return dp.back();
    }
};

文章来源:https://blog.csdn.net/m0_54919454/article/details/135651992
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。