动态规划

    xiaoxiao2025-03-14  23

    递归时间开销较大 动态规划主要的思想是:在程序运行过程中,将一些数据存放在表中,后面用到此数据时,直接调用,避免了重复计算问题。

    相关题目

    1. 斐波那契系数

    f(1) = f(2) = 1; f(n) = f(n-1) + f(n-2); (leetcode中限制了 n<30)

    法一: 暴力递归 O(2n)

    public: int f1(int n) { if(n < 1) return 0; if(n==1 || n==2) return 1; return f1(n-1) + f1(n-2); }

    leetcode 结果:

    法二:动态规划 O(N)

    从左到右依次求出每一项的值,通过顺序计算,得到第n项即可。

    class Solution { public: int fib(int n) { if(n<0) return 0; if(n==1 || n==2) return 1; int a1 = 1; int a2 = 1; int b = 0; for(int i=3; i<=n; i++) { b = a1 + a2; a1 = a2; a2 = b; } return b; } };

    leetcode 结果:

    2.爬楼梯问题

    问题描述: 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正整数。 示例 : 输入: 2 输出: 2 解释: 有两种方法可以爬到楼顶。 1. 1 阶 + 1 阶 2. 2 阶

    思路:在爬第n层台阶时,要么从第(n-1)层台阶迈一个台阶; 要么从第(n-2)层台阶,一次迈2个台阶;

    所以,第n阶的方法 = 到第(n-1)阶的方法 + 到第(n-2)阶的方法;

    与斐波那契系数问题相同,只是初始值不同。

    法一:暴力递归

    class Solution { public: int climbStairs(int n) { if(n<0) return 0; if(n==1) return 1; if(n==2) return 2; return climbStairs(n-1) + climbStairs(n-2); } };

    leetcode运行结果: 由于对于 n 的大小没有限制,所以运行超出时间限制

    法二:动态规划

    class Solution { public: int climbStairs(int n) { if(n<0) return 0; if(n==1) return 1; if(n==2) return 2; int a1 = 1; int a2 = 2; int b = 0; for(int i=3; i<=n; i++) { b = a1 + a2; a1 = a2; a2 = b; } return b; } };

    leetcode运行结果:

    3.矩阵最小路径和

    leetcode 第64题,题目描述: 给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。 说明:每次只能向下或者向右移动一步。 示例: 输入: [ [1,3,1], [1,5,1], [4,2,1] ] 输出: 7 解释: 因为路径 1→3→1→1→1 的总和最小。

    方法一:动态规划

    思路:定义一个辅助数组dp,数组大小和给定数组相同,dp[i][j]记录从(0,0)点到(i, j)点的最短路径,则最终我们想要的结果就是 dp[m-1][n-1]。对于第一行来说,因为只能往右走,所以,dp[0][j]就是前面的累加 + 此位置的value;对于第一列来说,只能往下走,dp[i][0] 也是前面的累加 + 此位置的value;对于其他的位置,那就等于 【它左边和它上面】这二者的最小值+此位置的value; class Solution { public: int minPathSum(vector<vector<int>>& grid) { if(grid.empty()) return 0; int m = grid.size(); int n = grid[0].size(); vector<vector<int> > dp(n,vector<int>(n));//记录从(0,0)走到(i,j)的最短路径 dp[0][0] = grid[0][0]; for(int j=1; j<n; j++) dp[0][j] = dp[0][j-1] + grid[0][j]; for(int i=1; i<m; i++) dp[i][0] += dp[i-1][0] + grid[i][0]; for(int i=1; i<m; i++) for(int j=1; j<n; j++) dp[i][j] = min(dp[i-1][j],dp[i][j-1]) + grid[i][j]; return dp[m-1][n-1]; } };

    leetcode 结果: 时间复杂度:O(m x n); 空间复杂度:O(m x n);

    最新回复(0)