动态规划基础练习(lc509,lc70,lc746,lc62,lc63,lc343,lc96)
Posted _BitterSweet
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划基础练习(lc509,lc70,lc746,lc62,lc63,lc343,lc96)相关的知识,希望对你有一定的参考价值。
动态规划——基础题目
力扣509.斐波那契数
题目描述
思路分析
- dp【i】的含义就是第 i 个斐波那契数的值
- 递推公式:dp【i】= dp【 i - 1】 + dp 【 i - 2】
- 初始化:dp【0】= 0 dp【1】 = 1
代码实现
普通版
class Solution {
public:
int fib(int n)
{
if(n == 0 || n== 1) return n;
vector<int> dp(n+1,0);
dp[0] = 0;
dp[1] = 1;
for(int i = 2; i < dp.size(); i++)
{
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}
};
优化版(空间复杂度优化到O(1))
class Solution {
public:
int fib(int n)
{
if(n < 2) return n;
int first = 0,second = 0,third = 1;
for(int i = 2; i<= n; i++)
{
first = second;
second = third;
third = first + second;
}
return third;
}
};
力扣70.爬楼梯
题目描述
思路分析
- dp【i】的含义是爬到第 i 层楼,存在dp【i】种方法
- 递推公式:dp【i】= dp【 i - 1】 + dp 【 i - 2】
- 不考虑dp【0】初始化,只初始化dp【1】= 1,dp【2】 = 2,从3开始递推
代码实现
普通版
class Solution {
public:
int climbStairs(int n)
{
if(n <= 1) return n;
vector<int> dp(n+1,0);
dp[1] = 1;
dp[2] = 2;
for(int i = 3; i<= n; i++)
{
dp[i] = dp[i-2] + dp[i-1];
}
return dp[n];
}
};
优化版(空间复杂度优化到O(1))
class Solution {
public:
int climbStairs(int n)
{
if(n <= 1) return n;
vector<int> dp(n+1,0);
int first = 0,second = 1,third = 2;
for(int i = 3; i<= n; i++)
{
first = second;
second = third;
third = first + second;
}
return third;
}
};
力扣746.使用最小花费爬楼梯
题目描述
思路分析
- 这道题刚开始一直没看懂题意什么意思,理解之后总结就是:要么第一步不收费,要么最后一步不收费
- dp【i】的含义是到达第 i 个台阶所花费的最少的体力
- 递推公式:dp【i】 = min(【dp【i - 1】, dp【i - 2】) + cost【i】
- 初始化:dp【0】 = cost【0】 dp【1】 = cost【1】
- 从前到后遍历cost数组
代码实现
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost)
{
vector<int> dp(cost.size(),0);
dp[0] = cost[0];
dp[1] = cost[1];
for(int i = 2;i < cost.size(); i++)
{
dp[i] = min(dp[i-2],dp[i-1]) + cost[i];
}
return min(dp[cost.size()-1],dp[cost.size()-2]);
}
};
力扣62.不同路径
题目描述
思路分析
- 机器人起点(0,0)终点(m-1,n-1)
- dp【i】【j】含义:表示从(0,0)出发到(i,j)有dp【i】【j】条不同的路径
- 所以路径来源就是一条横向的,一条纵向的,即dp【i-1】【j】和dp【i】【j-1】
- 递推公式:dp【i】 = dp【i - 1】【j】 + dp【i】【j - 1】
- 初始化
for (int i = 0; i < m; i++) dp[i][0] = 1;
for (int j = 0; j < n; j++) dp[0][j] = 1;
- 从左到右遍历
for (int i = 1; i < m; i++)
{
for (int j = 1; j < n; j++)
{
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
代码实现
class Solution {
public:
int uniquePaths(int m, int n)
{
vector<vector<int>> dp(m,vector<int>(n,0));
for(int i = 0;i < m; i++) dp[i][0] = 1;
for(int j = 0;j < n; j++) dp[0][j] = 1;
for(int i = 1;i < m; i++)
{
for(int j = 1; j < n; j++)
{
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
return dp[m-1][n-1];
}
};
力扣63.不同路径Ⅱ
题目描述
思路分析
- 因为加入了障碍物,所以我们只需要加几条特判语句,大体思路与上题没有什么变化
- dp【i】【j】含义:表示从(0,0)出发到(i,j)有dp【i】【j】条不同的路径
- 递推公式:
if (obstacleGrid[i][j] == 0)
{ // 当(i, j)没有障碍的时候,再推导dp[i][j]
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
- 初始化:开辟一个二维数组
vector<vector<int>> dp(m, vector<int>(n, 0));
for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) dp[i][0] = 1;
for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) dp[0][j] = 1;
- 遍历顺序:从左到右 一层一层
for (int i = 1; i < m; i++)
{
for (int j = 1; j < n; j++)
{
if (obstacleGrid[i][j] == 1) continue;
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
代码实现
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& nums)
{
int m = nums.size();
int n = nums[0].size();
vector<vector<int>> dp(m,vector<int>(n,0));
for(int i = 0; i < m && nums[i][0] == 0; i++) dp[i][0] = 1;
for(int j = 0; j < n && nums[0][j] == 0; j++) dp[0][j] = 1;
for(int i = 1; i < m; i++)
{
for(int j = 1; j < n; j++)
{
if(nums[i][j] == 1) continue;
dp[i][j] = dp[i-1][j] +dp[i][j-1];
}
}
return dp[m-1][n-1];
}
};
力扣343.整数拆分
题目描述
思路分析
- dp【i】的含义:拆解数字 i,得到的最大乘积dp【i】
- 怎么得到dp【i】:第一种:拆解 j,j * (i - j )
- 第二种:拆解(i - j),j * dp【i - j】
- 递推公式
dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));
- 初始化:没有必要初始化dp【0】,dp【1】,dp【2】 = 1
- 遍历顺序:i 从3开始,j 从 1枚举
for (int i = 3; i <= n ; i++)
{
for (int j = 1; j < i - 1; j++)
{
dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));
}
}
代码实现
class Solution {
public:
int integerBreak(int n)
{
vector<int> dp(n+1, 0);
dp[2] = 1;
for(int i = 3; i <= n; i++)
{
for(int j = 1; j < i - 1; j++)
{
dp[i] = max(dp[i],max((i - j) * j, j * dp[i - j]));
}
}
return dp[n];
}
};
力扣96.不同的二叉搜索树
题目描述
思路分析
代码实现
class Solution {
public:
int numTrees(int n)
{
vector<int> dp(n+1, 0);
dp[0] = 1;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= i; j++)
{
dp[i] += dp[j - 1] * dp[i - j];
}
}
return dp[n];
}
};
以上是关于动态规划基础练习(lc509,lc70,lc746,lc62,lc63,lc343,lc96)的主要内容,如果未能解决你的问题,请参考以下文章
代码随想录|day38|动态规划part01● 理论基础 ● 509. 斐波那契数 ● 70. 爬楼梯 ● 746. 使用最小花费爬楼梯