Leetcode动态规划专题
SL_World
中国科学院大学计算机应用技术专业在读研究生
展开
-
Leetcode|备忘录|42. 接雨水
一、动态规划——备忘录class Solution {public: int trap(vector<int>& height) { if (height.empty()) return 0; int size = height.size(); // max_left[i]记录第i点及其左边最高的柱子 vector<int> max_left(size, 0); // max_r.原创 2021-06-28 20:56:54 · 136 阅读 · 0 评论 -
Leetcode|有限状态自动机团灭买卖股票6道题
文章目录0 前言及问题描述1 有限状态自动机的使用2 股票问题框架2.1初始化2.3 总体框架3 买卖股票的最佳时机(k=1k = 1k=1)3.1 股票三维DP框架照搬(885ms)3.2 优化为二维DP(336ms)3.3 优化为O(1)O(1)O(1)(136ms)4 买卖股票的最佳时机(k=∞k = \inftyk=∞)4.1 股票DP框架照搬(12ms)4.2 优化为O(1)O(1)O(1)(0ms)5 买卖股票的最佳时机(k=∞k = \inftyk=∞)参考文献0 前言及问题描述大三编译原原创 2021-04-01 15:20:26 · 536 阅读 · 0 评论 -
Leetcode|树形排列|337. 打家劫舍 III
文章目录0 打家劫舍系列1 动态规划(记忆化递归)2 动态规划(一维树形状态转移)0 打家劫舍系列《Leetcode|线性排列|198. 打家劫舍》《Leetcode|环形排列|213. 打家劫舍 II》1 动态规划(记忆化递归)class Solution {private: unordered_map<TreeNode*, int> memo;public: int rob(TreeNode* root) { if (!root) return原创 2021-03-29 21:33:07 · 192 阅读 · 0 评论 -
Leetcode|环形排列|213. 打家劫舍 II
文章目录0 打家劫舍系列1 动态规划致谢0 打家劫舍系列《Leetcode|线性排列|198. 打家劫舍》1 动态规划class Solution {public: /**线性排列方法**/ int robRange(vector<int>& nums, int first, int end) { int size = end - first + 1; if (size == 1) return nums[first];原创 2021-03-29 17:36:59 · 222 阅读 · 0 评论 -
Leetcode|线性排列|198. 打家劫舍
1 动态规划【状态】:选择偷或者不偷对应房子的索引【选择】:①不偷第i家;②偷第i家【dp函数含义】:偷完前i家后所得最大金额为dp[i]【状态转移】: dp[i] = max(dp[i - 1], dp[i - 2] + nums[i])class Solution {public: int rob(vector<int>& nums) { int size = nums.size(); if (size == 1) return .原创 2021-03-29 16:50:31 · 165 阅读 · 0 评论 -
Leetcode|312. 戳气球(反向思维+区间动态规划)
1 动态规划(反向思维以分治)在求解问题前,考虑到作为状态的累计钱币数没有已知上限,是待求量。因此不能将累计钱币数作为dp索引,因此,我们要分析,这个问题能不能分解成小问题破解?显然,如果是按照先戳破第k个气球来思考,子问题之间是相互依赖的,问题只能分解,不能将小问题的解正确的合成。所以我们要做的是如何分解可以使得小问题之间相互独立?很多题解上来就说反向思维,但不会告诉你如何想到反向思维?其实是依靠正向逻辑的,只要按照正向逻辑,不论前向,后向还是什么左向右向思维都可以训练出来!!想要子问题相互独立.原创 2021-03-29 15:34:13 · 234 阅读 · 0 评论 -
Leetcode|887. 鸡蛋掉落(动规找最优BST根节点 + 将解作为状态)
文章目录1 动态规划(递归超时)2 动态规划(二分搜索优化,5%beat,1400ms)3 动态规划(将解作为状态,100%beat,0ms)致谢1 动态规划(递归超时)【状态】:①第i层扔碎了;②第i层扔没碎【dp函数含义】:剩余k个鸡蛋,有n层楼时,最坏情况下最少扔鸡蛋的次数为dp(k, n)【初始化】:状态有两个,因此需分别初始化,当楼层为0时,最少扔蛋次数为0;当剩余鸡蛋仅1个时,需做线性扫描,因此最坏情况下最少扔蛋次数为n【状态转移】minCont表示N课BST树中最小深度BST原创 2021-03-29 10:34:09 · 181 阅读 · 0 评论 -
Leetcode|651. 4键键盘(压缩成A和CV两键)
动态规划题目中提到的有四个按键,但实际上,我们可以压缩为2个选择,因为对于最优解,Ctrl+V一定在Ctrl+A-Ctrl+C两个按键后【dp数组含义】:按键i次后屏幕显示dp[i]个A【状态】:剩余可按键数量N【选择】:①按A; ②按Ctrl+V【状态转移方程】:dp[i] = max(dp[i - 1] + 1, dp[j - 2] * (i - j + 1));class Solution {public: int maxA(int N) { // dp数.原创 2021-03-26 21:24:02 · 379 阅读 · 1 评论 -
Leetcode|线性序列|10. 正则表达式匹配(两字符串前均补1个相同字符)
1 动态规划本题逻辑如下[1] if 两字符相同(或遇到.通配符)则两索引i,j同步后移1位[2] if 若两字符不同,且是因为遇到*通配符——[2.1] *通配符前1位字符p[j-1]与s[i]相同 → (0次 || 多次匹配) eg.s = aaa, p = a*——[2.2] *通配符前1位字符p[j-1]与s[i]不同 → 0次匹配 eg.s = aa, p = c*aa大多数本题题解都用的递归实现动态规划,但本题我使用dp数组,其初始化比递归实现简洁不少,但其中细节并不简单,特此..原创 2021-03-26 16:26:08 · 226 阅读 · 0 评论 -
Leetcode|线性序列|1312. 让字符串成为回文串的最少插入次数
1 动态规划本题解法与《Leetcode|线性序列|516. 最长回文子序列》高度相似【dp数组含义】:子串s[i, j]最少需要dp[i][j]次插入次数【状态转移方程】:两字符相等dp[i][j] = dp[i + 1][j - 1];两字符不等——则需考虑s[i + 1,j]和s[i,j - 1]dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]) + 1;class Solution {public: int minInser..原创 2021-03-25 10:45:28 · 176 阅读 · 0 评论 -
Leetcode|线性序列|516. 最长回文子序列
1 动态规划【dp数组含义】:s[i, j]的子序列最长为dp[i][j]【状态转移方程】:两字符相等——则回文子序列长度自增2dp[i][j] = dp[i + 1][j - 1] + 2;两字符不等——比较添加s[i]或s[j]可以增长子序列dp[i][j] = max(dp[i][j - 1], dp[i + 1][j]);完整代码如下class Solution {public: int longestPalindromeSubseq(string s) {.原创 2021-03-25 09:18:02 · 187 阅读 · 0 评论 -
Leetcode|线性序列|5. 最长回文子串(动规+双指针中心扩展)
文章目录0 前言1 动态规划2 双指针(中心扩展)0 前言本题和《Leetcode|线性序列|647. 回文子串》 很像,只是转而输出最长回文子串,但方法相同,单独对比每次回文子串大小,取最大和对应子串起始索引即可1 动态规划【dp数组含义】表示区间范围s[i,j] 的子串是否是回文子串,如果是dp[i][j]为true,否则为false当s[i] == s[j]时有如下两种情况共1个字符或2个相邻字符多个字符(>2)则需要判断s[i+1, j-1]内是否回文串class So原创 2021-03-24 23:37:37 · 284 阅读 · 0 评论 -
Leetcode|线性序列|647. 回文子串(暴力+动规+双指针中心扩展)
文章目录1 暴力解法2 动态规划3 双指针(中心扩展)1 暴力解法时间复杂度:O(n3)O(n^3)O(n3)空间复杂度:O(1)O(1)O(1)class Solution { public: bool valid(string& s, int first, int end) { for (int i = first, j = end; i < j; i++, j--) if (s[i] != s[j]) return fa原创 2021-03-24 17:50:35 · 262 阅读 · 0 评论 -
Leetcode|线性序列|409. 最长回文串(贪心算法)
1 贪心算法class Solution {public: int longestPalindrome(string s) { map<char, int> ch2cnt; for (auto& ch : s) ch2cnt[ch]++; int count = 0; // 是否有奇数 int isOdd = false; for (auto& m : ch2cnt) .原创 2021-03-24 15:53:13 · 361 阅读 · 0 评论 -
Leetcode|线性序列|72. 编辑距离
1 动态规划三个操作示意图如下边界初始化【状态转移方程】:// [1]删除1个字符 [2]插入一个字符 [3]替换1个字符 dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + 1)class Solution {public: int minDistance(string word1, string word2) { .原创 2021-03-23 20:09:55 · 168 阅读 · 0 评论 -
Leetcode|线性序列|583. 两个字符串的删除操作(变相LCS)
1 动态规划(二维动态规划)class Solution {public: int minDistance(string word1, string word2) { int asize = word1.size(); int bsize = word2.size(); vector<vector<int>> dp(asize + 1, vector<int>(bsize + 1, 0)); f.原创 2021-03-23 15:39:09 · 117 阅读 · 0 评论 -
Leetcode|线性序列|712. 两个字符串的最小ASCII删除和(变相LCS)
1 动态规划(变相最长公共子序列)【本题特点】:dp数组不仅能存储子序列的长度,还能存储子序列本身,确实可以很灵活dp[i][j] = dp[i - 1][j - 1] + s1[i - 1];dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);class Solution {public: int minimumDeleteSum(string s1, string s2) { int asize = s1.size(); .原创 2021-03-23 16:18:54 · 111 阅读 · 0 评论 -
Leetcode|线性序列|1143. 最长公共子序列(LCS二维动态规划)
动态规划class Solution {public: int longestCommonSubsequence(string text1, string text2) { int asize = text1.size(); int bsize = text2.size(); vector<vector<int>> dp(asize + 1, vector<int>(bsize + 1, 0)); .原创 2021-03-23 15:20:46 · 158 阅读 · 0 评论 -
Leetcode|线性序列|53/42. 连续子数组的最大和(暴力+贪心+动态规划包含结尾元素)
文章目录1 暴力 + sum小于0剪枝2 动态规划(未状态压缩)3 动态规划 (状态压缩)1 暴力 + sum小于0剪枝class Solution { public: int maxSubArray(vector<int>& nums) { int size = nums.size(); int maxSum = INT_MIN; for (int i = 0; i < size; i++) {原创 2021-03-23 11:15:06 · 225 阅读 · 0 评论 -
Leetcode|线性序列|354.俄罗斯套娃信封问题
动态规划(二维最长递增子序列问题)将一维问题简单扩展到二维,即两维同时升序(18%beat,约1400ms)class Solution {public: static bool cmp(vector<int>& a, vector<int>& b) { if (a[0] == b[0]) return a[1] < b[1]; return a[0] < b[0]; } int maxE.原创 2021-03-23 09:01:43 · 143 阅读 · 0 评论 -
Leetcode|完全背包|139. 单词拆分
1 动态规划(完全背包)class Solution {public: bool wordBreak(string s, vector<string>& wordDict) { int bagSize = s.size(); vector<bool> dp(bagSize + 1, false); dp[0] = true; for (int j = 1; j <= bagSize; j++).原创 2021-03-22 21:38:10 · 155 阅读 · 1 评论 -
Leetcode|完全背包|279. 完全平方数
1 动态规划(完全背包)没啥好说的,完全背包走就行了class Solution {public: int numSquares(int n) { vector<int> dp(n + 1, INT_MAX); dp[0] = 0; for (int i = 1; i * i <= n; i++) // 物品 for (int j = i; j <= n; j++) // 背包容量 .原创 2021-03-22 19:38:13 · 117 阅读 · 0 评论 -
Leetcode|排列+完全背包|70. 爬楼梯
1 动态规划(完全背包)太简单了, 排列+完全背包,直接上模板class Solution {public: int climbStairs(int n) { vector<int> dp(n + 1, 0); dp[0] = 1; for (int j = 1; j <= n; j++) for (int i = 1; i <= 2; i++) if (j >.原创 2021-03-22 17:14:28 · 115 阅读 · 0 评论 -
Leetcode|排列数|377.组合总和Ⅳ(回溯法超时+动规完全背包)
1 回溯法根据题目,你会发现,本问题有几个性质不同顺序为不同解(类比排列问题)——不宜用组合中的first技巧输入无重复元素——不宜用sort+跳过重复元素技巧问题的解可以包含重复元素——不宜用inPath技巧可见,基于排列/组合/子集的三板斧技巧均不宜用在本问题中,此时回溯法基本退化成了穷举法,具体代码如下class Solution {private: int size; int count = 0;public: void backtrack(vector.原创 2021-03-13 13:05:23 · 325 阅读 · 0 评论 -
Leetcode|完全背包|518. 零钱兑换 II
1 动态规划(完全背包)class Solution {public: int change(int amount, vector<int>& coins) { vector<int> dp(amount + 1, 0); dp[0] = 1; for (int i = 0; i < coins.size(); i++) // 完全背包:背包容量for循环升序 .原创 2021-03-22 16:34:41 · 123 阅读 · 0 评论 -
Leetcode动态规划模板
文章目录0 前言1 解题思考模式1.1 能不能用动态规划做?1.2 怎么用动态规划做?(七步走)2 动态规划模板2.1 通用模板2.2 背包模板2.2.1 01背包模板2.2.2 完全背包模板致谢0 前言路径基本要素说明核心基础穷举法需“聪明”穷举存在问题重叠子问题有众多相同子问题(eg.多个f(18)),需记录具备特点最优子结构原问题的解包含子问题的解状态转移思维模式自顶向下(推荐)当前状态如何由前一个状态推出目前所遇动态规划问题一般形式包原创 2021-03-22 15:54:31 · 917 阅读 · 0 评论 -
Leetcode|01背包|474. 一和零(二维01背包)
1 动态规划(二维01背包)【dp[i][j]数组含义】:容量0的个数最多为i且1的个数最多为j的情况下,两个维度容量的背包下最多的子集数【状态转移方程】:dp[i][j] = max(dp[i][j], dp[i - cont0][j - cont1] + 1)class Solution {public: int findMaxForm(vector<string>& strs, int m, int n) { int size = strs.siz.原创 2021-03-21 17:47:18 · 165 阅读 · 0 评论 -
Leetcode|01背包|494. 目标和(回溯法+01背包)
1 回溯法(AC,29%beat,745ms)回溯法需做好剪枝优化和记录结果的数据结构不能太复杂就能飘过,比如不能用vector记录结果class Solution {private: int size; int count = 0; int sum = 0;public: void backtrack(vector<int>& nums, int curSum, int first) { if (curSum == sum) c.原创 2021-03-21 15:18:55 · 247 阅读 · 0 评论 -
Leetcode|01背包|1049. 最后一块石头的重量 II(两背包)
动态规划(两个01背包)背包1 - 背包2 = (sum - 背包2) - 背包2class Solution {public: int lastStoneWeightII(vector<int>& stones) { int size = stones.size(); int sum = accumulate(stones.begin(), stones.end(), 0); int halfSum = sum / 2;.原创 2021-03-20 19:51:06 · 234 阅读 · 0 评论 -
Leetcode|01背包|416. 分割等和子集
动态规划(01背包问题)【dp数组含义】:容量(和)为j的情况下,能达到的最大容量(和)dp[j]【状态转移方程】:dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])最后判断dp[halfSum]是否等于halfSum即可class Solution {public: bool canPartition(vector<int>& nums) { int size = nums.size(); i.原创 2021-03-20 17:01:45 · 172 阅读 · 1 评论 -
Leetcode|完全背包|322. 零钱兑换
1 动态规划实际状态转移方程如下:dp[状态i] = min(1 + dp[状态i - 选择1], 1 + dp[状态i - 选择2], 1 + dp[状态i - 选择3]....);其中,我们对多个元素求最小怎么求的?是不是下面这样int maxNum = INT_MAX;for (int i = 0; i < size; i++) maxNum = min(maxNum, num[i]);所以就有了状态转移方程在程序中的主流表现形式dp[状态i] = min(dp[状态i],.原创 2021-03-18 12:41:46 · 112 阅读 · 0 评论 -
Leetcode|线性序列|300. 最长递增子序列
1 动态规划注意:dp数组的定义一定要正确,否则难以定义正确的状态转移方程【本题dp数组定义】:dp[i]表示前i个元素中最长递增子序列长度(必须包含第i个尾元素, 否则无法确定状态如何转移)class Solution {public: int lengthOfLIS(vector<int>& nums) { int size = nums.size(); // dp[i]表示前i个元素中最长递增子序列长度(必须包含第i个尾元素, .原创 2021-03-18 16:01:38 · 152 阅读 · 0 评论