leetcode 62 不同路径-动态规划(c++和python)

目录

动态规划

特点

求法

斐波那契数列 (简单)

递归方法(时间复杂度O(2^n))

动态规划(时间复杂度O(n))

路径问题(中等)

c++代码:

python代码:


动态规划

特点

  1. 问题的答案依赖于问题的规模,比如等差数列(2, 4, 6, 8, ..., 2n). 当前的问题n的规模,决定当前的答案是f(n) = 2n;
  2. 当前问题的答案可以通过之前问题的答案推导而来,比如f(n) = f(n-1) + 2。

求法

使用动态规划的前提是没有显示方程,不然直接使用显示方程f(n) = 2n就可以求出结果,我们只能得出状态转移方程。

  1. 建立状态转移方程,通过前面已知答案,建立状态转移方程,比如上面的f(n) = f(n-1) + 2;
  2. 缓存之前的结果并复用,比如之前求过f(99),那当前f(100) = f(99) + 2即可;
  3. 从小往大推到出最终结果。

斐波那契数列 (简单)

0, 1, 1, 2, 3, ...,

当前值是前两个值的和。

按照求法,首先得到状态转移方程:f(n) = f(n-1) + f(n-2),然后有两种方法求解。

递归方法(时间复杂度O(2^n))

def fib(n):
    if n < 2:  # 0, 1, 1, 2, ...
        return n
    else:
        return fib(n-1) + fib(n-2)


if __name__ == '__main__':
    print(fib(3))

动态规划(时间复杂度O(n))

即把之前的结果都缓存下来,利用之前的结果,来求当前的答案。

def fib(n):
    results = list(range(n+1))  # 缓存以往结果
    for i in range(n+1):  # 按顺利从小到大
        if i < 2:
            results[i] = i  # n = 0时,i也等于0; n=1, i=1
        else:
            results[i] = results[i-1] + results[i-2]  # n=2,会先过两遍if,求得前面两个值.
    return results[n]


if __name__ == '__main__':
    print([fib(i) for i in range(10)])

路径问题(中等)

题目:

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

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

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

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

提示:

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

即从f(0,0)走到f(6,8),有多少条路径?

f(0, 0) = 0

f(0,1) = 1

f(1,0) = 1

f(1,1) = f(1,0) + f(0,1) = 2

f(0,2) = f(0,1) = 1

f(1,2) = f(0,2) + f(1,1) = 1 + 2 = 3

f(2,0) = 1

f(2,1) = f(1,1) +f(2,0) = 2 + 1 = 3

....

f(m, n) = f(m-1,n) + f(m, n-1)

得出推导式是f(m, n) = f(m-1,n) + f(m, n-1),其中m, n分别是行列数,且1 <= m, n <= 100

c++代码:

执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户

内存消耗:6.3 MB, 在所有 C++ 提交中击败了55.63%的用户

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> results(m, vector<int>(n, 1));  // # m行,n列 初始值为1
        
        /*题目限定的m和n从1开始
        r[1,1] = r[0,1] + r[1,0] = 1 + 1 = 2
        r[1,2] = r[0,2] + r[1,1] = 1 + 2 = 3
        r[1,3] = r[0,3] + r[1,2] = 1 + 3 = 4
        ...
        r[2,1] = r[1,1] + r[2,0] = 2 + 1 = 2
        ...
        */
        for (int i = 1; i < m; i++)
            for (int j = 1; j < n; j++)
            {
                results[i][j] = results[i-1][j] + results[i][j-1];
            }
        return results[m-1][n-1];
    }
};

python代码:

执行用时:12 ms, 在所有 Python 提交中击败了94.21%的用户

内存消耗:12.9 MB, 在所有 Python 提交中击败了76.84%的用户

class Solution(object):
    def uniquePaths(self, m, n):
        """
        :type m: int
        :type n: int
        :rtype: int
        """
        results = [[1] * n] * m  # m行,n列 初始值为1

        # 题目限定的m和n从1开始
        # r[1,1] = r[0,1] + r[1,0] = 1 + 1 = 2
        # r[1,2] = r[0,2] + r[1,1] = 1 + 2 = 3
        # r[1,3] = r[0,3] + r[1,2] = 1 + 3 = 4
        # ...
        # r[2,1] = r[1,1] + r[2,0] = 2 + 1 = 2
        # ...
        for i in range(1, m):  # 一行一行的来
            for j in range(1, n):
                results[i][j] = results[i-1][j] + results[i][j-1]  
            
        return results[m-1][n-1]

参考:如何理解动态规划? - 知乎以下是我学习动态规划的全部心血。文章核心内容不长,文末的三个例子占了大部分篇幅,如果想快速了解,不…https://www.zhihu.com/answer/883302989

猜你喜欢

转载自blog.csdn.net/jizhidexiaoming/article/details/121349640