您的位置:首页 > 汽车 > 新车 > 力扣hot100 -- 动态规划(上)

力扣hot100 -- 动态规划(上)

2024/10/6 5:31:44 来源:https://blog.csdn.net/csdner250/article/details/140137155  浏览:    关键词:力扣hot100 -- 动态规划(上)

目录

❄技巧

🌼爬楼梯

🍔杨辉三角

🌊打家劫舍

🐎完全平方数

🌼零钱兑换

🌼单词拆分


❄技巧

动态规划dp-CSDN博客

👆花 5 分钟快速刷一遍

花 10 分钟浏览一下 线性DP + 背包DP👇

30个题型+代码(冲刺2023蓝桥杯)(下)_挑战程序设计竞赛代码-CSDN博客

🌼爬楼梯

70. 爬楼梯 - 力扣(LeetCode)

/*
dp[i] : 爬到第 i 层的方法数
dp[i] = max(dp[i - 2] + dp[i - 1]) 每次爬 1 或 2 台阶
初始化 dp[0], dp[1]
前到后遍历
*/
class Solution {
public:int climbStairs(int n) {if (n <= 3)return n;int dp[n + 1];dp[0] = 1, dp[1] = 2;// 类似斐波那契for (int i = 2; i < n; ++i)dp[i] = dp[i - 1] + dp[i - 2];return dp[n - 1];}
};

🍔杨辉三角

118. 杨辉三角 - 力扣(LeetCode)

/*
dp[i][j] : 第 i 行, 第 j 列的数字
dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]
观察可得:初始化 dp[i][0], dp[i][i] 左右边界的两条边 = 1
*/
class Solution {
public:vector<vector<int>> generate(int numRows) {vector<vector<int>> ans;int dp[31][31];for (int i = 0; i < numRows; ++i)dp[i][0] = 1, dp[i][i] = 1;ans.push_back({1});if(numRows >= 2)ans.push_back({1, 1});for (int i = 2; i < numRows; ++i) {vector<int> temp;temp.push_back(1);for (int j = 1; j < i; ++j) {dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];temp.push_back(dp[i][j]);}temp.push_back(1);ans.push_back(temp);}return ans;}
};

🌊打家劫舍

198. 打家劫舍 - 力扣(LeetCode)

/*
dp[i] : 只偷前 i 号房屋的最大值, i 从 0 开始
dp[i] = max(dp[i - 2] + nums[i], dp[i - 1])
初始化 : dp[0] = nums[0], dp[1] = max(nums[0], nums[1])
*/
class Solution {
public:int rob(vector<int>& nums) {int n = nums.size();int dp[101];if (n == 1) return nums[0];if (n == 2) return max(nums[0], nums[1]);dp[0] = nums[0], dp[1] = max(nums[0], nums[1]);for (int i = 2; i < n; ++i)dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);return dp[n - 1];}
};

🐎完全平方数

279. 完全平方数 - 力扣(LeetCode)

本题完全背包 -- 同 “零钱兑换”

01 背包,每个物品只选 1 个或不选;完全背包,每个物品可以选无数个

时间 O(n*\sqrt{n})

/*
dp[i] : 完全平方数的和为 i 的最少数量dp[i] = min(dp[i], dp[i - j*j] + dp[j*j])
即 dp[i] = min(dp[i], dp[i - j*j] + 1)
和为 i 的最小个数 = 
min(当前最大个数 dp[i], 和为 i - j*j 的最小个数 + 1)初始化 : dp[i] = 1+1+1+... = i 取最大值
*/
class Solution {
public:int numSquares(int n) {int dp[10001];dp[0] = 0; // 防止 dp[16 - 4*4] 没有for (int i = 1; i <= n; ++i) {dp[i] = i; // 初始化最大值for (int j = 1; j*j <= i; ++j)dp[i] = min(dp[i], dp[i - j*j] + 1);}return dp[n];}
};// 0 1 2 3 4 5 6 7 8 9(初始化)

🌼零钱兑换

322. 零钱兑换 - 力扣(LeetCode)

完全背包,同上一题 “完全平方数” 

auto x : 数组,不会改变原数组的值,只能遍历,无法改变原数组的值

改变原数组的值直接数组访问 a[i]

时间 O(Sn),S是 amount,n 是 coins 数量 

/*
dp[i] : 金额总和为 i 的最少数量
dp[i] = min(dp[i], dp[i - coins[j]] + 1)
初始化 :  dp[0] = 0
*/
class Solution {
public:int coinChange(vector<int>& coins, int amount) {int dp[amount + 10];for (int i = 1; i <= amount; ++i)dp[i] = amount + 1; // 初始化最大值dp[0] = 0; for (int i = 1; i <= amount; ++i)for (int j = 0; j < coins.size(); ++j)if (i >= coins[j])dp[i] = min(dp[i], dp[i - coins[j]] + 1);return dp[amount] == amount + 1 ? -1 : dp[amount];}
};

🌼单词拆分

139. 单词拆分 - 力扣(LeetCode)

注意,s.substr(i, j) 表示下标 i 开始,连续的 j 个字符

时间 O(n^2)

/*
dp[i] : s 的前 i 位是否可以用 wordDict 中的字符串表示
dp[i] = dp[j] && hash.find(s.substr(j, i - j)) != hash.end()
解释:前 j 位可以找到,且 [j, i] 能用 wordDict 中字符串表示
初始化 : dp[0] = true
*/
class Solution {
public:bool wordBreak(string s, vector<string>& wordDict) {int n = s.size();// 转化为哈希表,便于查找unordered_set<string> hash(wordDict.begin(), wordDict.end());vector<bool> dp(n + 1, false);dp[0] = true;for (int i = 1; i <= n; ++i) // 前 i 位(1开始)for (int j = 0; j < i; ++j) // 左边界if (dp[j] && hash.find(s.substr(j, i-j)) != hash.end() ) {dp[i] = true;break;}return dp[n];}
};

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com