个人技术分享

动态规划理论基础

文档讲解:代码随想录
视频讲解:从此再也不怕动态规划了,动态规划解题方法论大曝光 !| 理论基础 |力扣刷题总结| 动态规划入门

动态规划解题五步法:

  1. 确定dp数组以及下标的含义;
  2. 确定递推公式;
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

509. 斐波那契数

题目链接:509. 斐波那契数

文档讲解:代码随想录

视频讲解:手把手带你入门动态规划 | LeetCode:509.斐波那契数

思路

  1. 确定dp数组以及下标的含义:dp[i]表示第i个数的斐波那契数值是dp[i]
  2. 确定递推公式:dp[i] = dp[i - 1] + dp[i - 2]
  3. dp数组如何初始化:dp[0] = 0, dp[1] = 1
  4. 遍历顺序:从前向后遍历

代码

class Solution {
public:
	int fib(int n) {
		if (n <= 1)
			return n;
		vector<int> dp(n + 1);
		dp[0] = 0;
		dp[1] = 1;
		for (int i = 2; i <= n; i++) {
			dp[i] = dp[i - 1] + dp[i - 2];
		}

		return dp[n];
	}
};

70. 爬楼梯

题目链接:70. 爬楼梯

文档讲解:代码随想录

视频讲解:带你学透动态规划-爬楼梯(对应力扣70.爬楼梯)| 动态规划经典入门题目

思路

  1. 确定dp数组以及下标的含义:dp[i]表示爬到第i层楼梯,有dp[i]种方法
  2. 确定递推公式:dp[i] = dp[i - 1] + d[i - 2] 可以从前一层上一个台阶,或者从前两层上两个台阶
  3. dp数组如何初始化:dp[1] = 1, dp[2] = 2
  4. 遍历顺序:从前向后遍历

代码

class Solution {
public:
	int climbStairs(int n) {
		if (n <= 2)
			return n;
		// dp数组
		vector<int> dp(n + 1);

		// dp数组初始化
		dp[1] = 1;
		dp[2] = 2;

		// 状态转移方程
		// dp[i] = dp[i - 1] + dp[i - 2]
		for (int i = 3; i <= n; i++) {
			dp[i] = dp[i - 1] + dp[i - 2];
		}

		return dp[n];
	}
};

746. 使用最小花费爬楼梯

题目链接:746. 使用最小花费爬楼梯

文档讲解:代码随想录

视频讲解:动态规划开更了!| LeetCode:746. 使用最小花费爬楼梯

思路

  1. 确定dp数组以及下标的含义:dp[i]表示爬到第i层楼梯,花费的最少体力为dp[i]
  2. 确定递推公式:dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]) 从前一层上台阶和从前两层上台阶花费体力的较小者
  3. dp数组如何初始化:dp[0] = 0, dp[1] = 0
  4. 遍历顺序:从前向后遍历

代码

class Solution {
public:
   int minCostClimbingStairs(vector<int>& cost) {
   	vector<int> dp(cost.size() + 1);
   	dp[0] = 0;
   	dp[1] = 0;
   	for (int i = 2; i < dp.size(); i++) {
   		dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
   	}

   	return dp[dp.size() - 1];
   }
};