
动态规划
dp........
重you小垃
这个作者很懒,什么都没留下…
展开
-
常见dp总结
-----------------------------------------------01背包---------------------------------------一共有n件物品,第i(i从0开始)件物品的重量为w[i],价值为v[i]。在总重量不超过背包承载上限W的情况下,能够装入背包的最大价值是多少?暴力:复杂度达到O(2^n)注意到:前i件物品放入背包所获得最大价值可由前前i-1件物品放入背包所获得最大价值得到,因此可以用DP来解决DP(时间复杂度:O(n×W), 空间复杂度:原创 2021-11-24 20:24:53 · 446 阅读 · 0 评论 -
leetcode2312. 卖木头块(困难,周赛)
思路:dp如何想到dp的?垂直/水平切割,得到更小的子问题先垂直再水平和先水平再垂直会得到同样大小的两块木块,因此1:存在重复子问题对于同样高和宽的两个木块所获得的最多钱数和得到这两个木块的过程无关,因此2:无后效性获得两块小木块的最多钱数,就获得了大木块的最多钱数,因此3:最优子结构满足以上三个条件,因此->dp状态转移:p[m][n]表示高m宽n的木块能获得的最大钱数dp[m][n]能直接卖的话获得一个pricedp[m][n]=max(dp[m][j]+dp[m][n-j]),1.原创 2022-06-30 21:26:24 · 253 阅读 · 0 评论 -
leetcode32.最长有效括号(困难)
自己一开始不会做。。。1:看到最长子串,首先想到的是DP?但是转移方程怎么列?没头绪啊(见方法一)2:看到是括号匹配,想到用栈,但是暴力出每个子串,然后用栈来判断,O(n^3)的复杂度,很明显会超时,怎么做?(见方法二)3:想到’(‘加一,’)‘减一,判断是否等于0来判断是否匹配,然而出现’)('怎么处理?(见方法三)方法一:DP,时间空间都是O(n)dp[i]表示以s[i]结尾的最长子串。case1:当前字符是’(’,必然不匹配。case2:当前字符s[i]是’)’----------..原创 2021-10-21 11:59:06 · 134 阅读 · 0 评论 -
leetcode718. 最长重复子数组(中等, 字符串hash)
思路一:dp O(n*m)dp[i][j]表示 nums1[0…i]与 nums2[0…j]的最长重复子数组转移方程:如果nums1[i] == nums2[j]:dp[i][j] = dp[i-1][j-1]+1否则:dp[i][j] = 0ans:dp数组中的最大值class Solution {public: int findLength(vector<int>& nums1, vector<int>& nums2) { ..原创 2022-05-28 10:45:59 · 242 阅读 · 0 评论 -
leetcode343. 整数拆分(中等)
思路:dp具体思路:枚举要减的段。dp[i]表示i剪的话获得的最大乘积转移方程:dp[i] = (dp[i - j], i - j) * j; (另外长度i - j 要么剪要么不剪 取最大值)边界:dp[1] = 1class Solution {public: int integerBreak(int n) { vector<int> dp(n + 1); dp[1] = 1; for (int i = 2; i <.原创 2022-05-07 19:06:16 · 201 阅读 · 0 评论 -
leetcode213. 打家劫舍 II(中等)
思路:dp难点:环怎么破?偷第一间,则不能偷最后一间,也就是 [0,n-2]中打家劫舍的模板不偷第一间,则可以偷最后一间,也就是 [1,n-1]中打家劫舍的模板因此状态转移跟打家劫舍一模一样dp[i][0]表示不盗nums[i]的前提下前i所能偷盗的最大金额dp[i][1]表示盗nums[i]的前提下前i所能偷盗的最大金额转移方程如下:dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]);dp[i][1] = dp[i - 1][0] + nums[i]..原创 2022-05-06 17:47:29 · 209 阅读 · 0 评论 -
leetcode120. 三角形最小路径和(中等)
思路:dpdp[i][j]表示从[0][0]到[i][j]的最短路径长度转移方程:dp[i][j]=min(dp[i-1][j],dp[i-1][j-1])+nums[i][j]ans:dp[n-1][0…n-1]中的最小值class Solution {public: int minimumTotal(vector<vector<int>>& triangle) { int n = triangle.size(); ..原创 2022-05-05 19:27:17 · 190 阅读 · 0 评论 -
剑指offer13.机器人的运动范围(中等)
一开始的误解:以为满足数位之和<=k的地方都能到,实际上有可能是到不了的,因为不是x+y而是x的每一位和y的每一位相加!!!思路(就是二维数组中地图中相邻1的个数,套模板即可,模板记不清了)1:BFS int xy[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};bool flag[m][n];queue<pair<int, int>> q;q.push(make_pair(0, 0));flag[0][0] = true;while .原创 2021-10-11 20:21:44 · 129 阅读 · 0 评论 -
leetcode63. 不同路径 II(中等)
类似的题:leetcode62.不同路径(中等)https://blog.youkuaiyun.com/zhangjiaji111/article/details/121802934思路:dpdp[i][j]表示[0][0]到[i][j]的路径数,这样能滚动数组优化转移方程:dp[i][j]=dp[i-1][j]+dp[i][j-1]边界:dp[0][0] = (obstacleGrid[0][j] == 0); dp[0][1…m-1]初始化从左边得到class Solution {public:...原创 2022-05-04 22:17:47 · 341 阅读 · 0 评论 -
leetcode45.跳跃游戏Ⅱ(中等)
leetcode55.跳跃游戏:https://blog.youkuaiyun.com/zhangjiaji111/article/details/120659495方法一:贪心具体思路:当前的位置跳的位置为:下下次可以跳得更远的位置。 通过局部最优得到全局最优解。class Solution {public: int jump(vector<int>& nums) { int n = nums.size(), index = 0, ans = ..原创 2021-12-12 23:03:06 · 1853 阅读 · 0 评论 -
leetcode956. 最高的广告牌(困难)
思路一:暴力,每个元素有三种选择(假设有有两组,一边高‘+’ 一边低‘-’):+ - 不选,因此可以考虑用暴力dfs,每层有三个分支,然而,O(3^20)的复杂度肯定是会超时的,O(3 ^15)的话还差不多。。。思路二:dp刚开始的想法:感觉有点像 leetcode494.目标和(中等)https://blog.youkuaiyun.com/zhangjiaji111/article/details/122262922这道题,然而:那道题是分两组(+ -)这道题是分三组(+ - 不用),所以这道题找不到跟..原创 2022-05-02 09:55:15 · 344 阅读 · 0 评论 -
leetcode956.最高的广告牌(困难)
class Solution {public: int tallestBillboard(vector<int>& rods) { //暴力:3^n //即分三组:1 -1 0,使得和为0的前提下正数和最大 //类似目标和,但是目标和sum找不到关系 //dp[i][左边和][右边和]的话 20*5000*5000空间上就炸了,考虑状态中记录差绝对值,最大高度 /*状态:dp[i][高低两边的差值绝原创 2022-05-01 21:07:25 · 288 阅读 · 0 评论 -
leetcode1770. 执行乘法运算的最大分数(中等)
思路:dpdp[i][j]表示: multipliers前i个元素中,j为前面拿掉的个数 ,i-j为后面拿掉的个数 所获得的分数i:0…m-1 j:0…i+1转移方程:dp[i][j]=max(dp[i-1][j-1]+nums[j-1]*multipliers[i], dp[i-1][j]+nums[n - i + j - 1]*multipliers[i])也就是表示要么在前面取,要么在后面取一个。为什么是n - i + j - 1? 因为一共i + 1个元素,前面j个,所以后面i+1-...原创 2022-04-29 16:39:17 · 357 阅读 · 0 评论 -
leetcode1049. 最后一块石头的重量 II(中等)
思路:01背包为什么能转化为01背包问题呢?一次碰撞就是一正一负 ,计算出的结果再跟其他一正一负的过程,每个元素之前构造+ /- 形成的表达式得到的最小正整数就是石头的最小重量,就转化为背包容量为sum/2最多能放多少重量的石头,每个石头只能选一次,即0 - 1背包问题dp[i][j]表示容量为j的背包,放前i个元素最多能放多少重量的石头转移方程:dp[i][j]=max(dp[i-1][j],dp[i-1][j-stones[i]] + stones[i])dp[n-1][sum/2] 为...原创 2022-04-28 18:24:11 · 305 阅读 · 1 评论 -
leetcode474. 一和零(中等)
思路:0-1背包问题 (滚动数组后,从右向左更新)跟背包问题最大的区别是:这道题有两个限制,0-1背包是一个限制dp[i][j][k]表示在0限制为j 1限制为k,前i个最大子集的个数。转移方程:dp[i][j][k]=max(dp[i][j-a][k-b]+1,dp[i-1][j][k])边界全是0。class Solution {public: pair<int, int> get(const string& s) { int a = 0,..原创 2022-04-27 21:20:40 · 279 阅读 · 0 评论 -
leetcode64.最小路径和(中等)
解法:动态规划状态转移方程为:dp[i][j] = min(dp[i-1][j],dp[i][j-1])+grid[i][j]class Solution {public: int minPathSum(vector<vector<int>>& grid) { int m = grid.size(), n = grid[0].size(); vector<vector<int>> dp..原创 2021-10-26 10:55:15 · 122 阅读 · 0 评论 -
leetcode122.买股票的最佳时机II(中等)
思路一:贪心(长期的过程转化为每一步)实现细节:(1) 连续上升时:nums[j]-nums[i]=(nums[i+1]-nums[i])+(nums[i+2]-nums[i+1])+…+(nums[j]-nums[j-1]) 将连续的上升过程转化为小段的上升过程,即如果nums[i]>nums[i-1]即在nums[i]进行买卖(2) 连续下降时:转化为小段的下降过程,此时不买不卖class Solution {public: int maxProfit(vector&l...原创 2022-04-02 15:41:36 · 139 阅读 · 0 评论 -
leetcode1025. 除数博弈(简单)
思路一:dp从小到大写一下:1:alice输2:alice只能选1,bob输,alice赢3:alice选1转到2:alice输;dp[i]表示i时alice赢还是输,假设j是i的因子,dp[i - j]有一个存在false,则dp[i]=true;否则dp[i]只能为falseclass Solution {public: bool divisorGame(int n) { vector<int> dp(n + 1); if (n ..原创 2022-04-21 20:26:07 · 171 阅读 · 0 评论 -
leetcode面试题 17.16. 按摩师(简单)
思路一:dp(当前状态有前两个状态决定)dp[i]表示前i总时长转移方程: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 massage(vector<int>& nums) { //dp[i]表示前i总时长 dp[i]=max(dp[i-2]+nums[i],dp[i-1]) ..原创 2022-04-21 20:02:24 · 430 阅读 · 0 评论 -
leetcode746. 使用最小花费爬楼梯(简单)
跟爬楼梯思想很类似。leetcode70.爬楼梯(简单):https://blog.youkuaiyun.com/zhangjiaji111/article/details/121801918思路:dpdp[i]表示到i位置的台阶的最低花费dp[n]=min(dp[n-1]+cost[n-1],dp[n-2]+cost[n-2])边界:dp[0] = dp[1] = 0;class Solution {public: int minCostClimbingStairs(vector<i...原创 2022-04-21 19:43:40 · 176 阅读 · 0 评论 -
leetcode121 122 309 714 123 188股票买卖问题
自己的思路:时间空间都是O(n)定义一个数组存右边的最大值(也可以存左边的最小值),ans = max(anx, rightmax[i]-prices[i]);class Solution {public: int maxProfit(vector<int>& prices) { int n = prices.size(); if (n < 2) return 0; vector<int>..原创 2021-10-15 10:51:59 · 164 阅读 · 0 评论 -
leetcode392.判断子序列(简单)
思路一:遍历一遍t ,看能匹配s的最长下标能不能达到 s.size()。class Solution {public: bool isSubsequence(string s, string t) { int index = 0; for (int i = 0; i < t.size() && index < s.size(); ++i) { if (t[i] == s[index]) i..原创 2022-04-19 21:35:45 · 136 阅读 · 0 评论 -
LCD07.传递信息(简单)
题意分析:本质是求有向图中第k层有多少个n-1.解法一:dfs时间复杂度:O(n^k),即最多每个结点均指向n-1个结点具体细节:当到第k层时return ;class Solution {public: vector<vector<int>> graph; int ans = 0; void dfs(int n, int index, int k, int layer) { if (layer == k) { ..原创 2022-04-17 12:06:02 · 169 阅读 · 0 评论 -
leetcode300.最长递增子序列(中等)
解法一:dp 时间复杂度O(n^2)class Solution {public: int lengthOfLIS(vector<int>& nums) { int n = nums.size(); vector<int> dp(n, 1); int ans = 1; for (int i = 1; i < n; ++i) { for (int j = 0; j...原创 2022-01-26 14:34:19 · 379 阅读 · 0 评论 -
leetcode53.最大子数组和(简单)
解法一:dpdp[i]表示以 nums[i] 结尾的连续子数组的最大值。dp[i] = (dp[i - 1] + nums[i], nums[i])ans: dp数组中的最大值class Solution {public: int maxSubArray(vector<int>& nums) { int n = nums.size(); int dp = nums[0]; int ans = nums[0]; ...原创 2022-04-12 12:45:29 · 217 阅读 · 0 评论 -
leetcode5.最长回文子串(中等)
class Solution {public: string result; int maxlen = 0; void huiwen(int left, int right, string str); string longestPalindrome(string s) { if (s.length() == 0) return result; int left, right; for (int i = 0; i < .原创 2020-12-10 14:50:09 · 104 阅读 · 1 评论 -
leetcode91.解码方法(中等,代码细节)
方法:dp状态转移方程:s[i]是’0’ 的情况下:如果s[i-1]是’1‘或者’2’:dp[i] = (i - 2 >= 0) ? dp[i - 2] : 1;否则:return 0;s[i]不是’0’ 的情况下:dp[i] = dp[i - 1]。如果s[i -1] s[i]构成的两位数在10到26之间,dp[i] += (i - 2 >= 0) ? dp[i - 2] : 1;边界:如果(s[0] == ‘0’) return 0;否则 dp[0] = 1;c..原创 2022-03-03 20:43:17 · 165 阅读 · 0 评论 -
leetcode647.回文子串(中等)
自己的想法:穷举所有。。。。复杂度太高了class Solution {public: bool judge(string str); int countSubstrings(string s) { long count = 0; for (int i = 0; i < s.length(); i++){ for (int j = 1; j <= s.length() - i; j++) if..原创 2020-11-22 20:05:23 · 118 阅读 · 0 评论 -
leetcode494.目标和(中等)
思路一:dfs —>复杂度过高O(n^2)剪枝优化:加入前缀和1:由于每个元素都是非负整数,如果当前得到的值+后面所有元素的和<target 则return ;2:如果当前得到的值+后面所有元素的和的相反数>target 则return ;class Solution {public: int ans = 0; vector<int> sums; void dfs(vector<int>& nums, int inde...原创 2021-12-31 22:36:42 · 378 阅读 · 0 评论 -
leetcode416.分割等和子集(中等)
自己没思路。。。思路:01背包问题题目可以转化为:在nums数组中找出一些元素,这些元素的和为sum/2,由于每个元素只能选一次,所以等价于0-1背包问题(传统的01背包的限制是背包容量有限,这道题的限制是和为固定值)具体细节:dp[i][j]表示:下标i前面所有的元素是否能组成j转移方程:dp[i][j] = dp[i - 1][j - nums[i]] | dp[i - 1][j] (选nums[i] 不选nums[i] 两个中有一个构成即可,所以用位运算’|’)边界:dp[0][..原创 2021-12-29 22:07:20 · 262 阅读 · 0 评论 -
leetcode312.戳气球(困难)
解法:区间dp->大区间的最优解由小区间的最优解得到具体:题目说是依次删掉,可以反过来思考,按照一个一个添加来思考。dp[i][j]代表(i,j)所能获得的硬币的最大数量状态转移方程思考:依次枚举在(i,j)添加的第一个元素。因此:dp[i][j]=dp[i][k]+dp[k][j]+tmp[i]*tmp[k]*tmp[j] //tmp为nums左右两端都加1组成的数组class Solution {public: int maxCoins(vector<int&g...原创 2021-12-24 11:47:44 · 579 阅读 · 0 评论 -
leetcode279.完全平方数(中等)
方法一:看到最少->想到bfs。class Solution {public: int numSquares(int n) { queue<int> q; unordered_set<int> ust; for (int i = 1; i * i <= 10000; ++i) { ust.insert(i * i); } q.push(..原创 2021-12-16 13:08:00 · 191 阅读 · 0 评论 -
leetcode139.单词拆分(中等)
方法:dpdp[i]表示s[0…i]是否可以用wordDict来表示。dp[i]存在=dp[j:0…i-1]其中一个为true 且 s.substr(j+1,i-j)存在;边界:dp[0]=true;定义一个长度为wordDict.size()+1的数组。class Solution {public: bool wordBreak(string s, vector<string>& wordDict) { unordered_set<st...原创 2021-12-15 16:45:56 · 157 阅读 · 0 评论 -
leetcode72.编辑距离(困难)
方法:dp具体:dp[i][j]表示:word1[0…i]到word2[0…j]的最小操作数。如果word1[i]==word2[j],dp[i][j]=dp[i-1][j-1]否则为三种操作方法得到dp[i][j]=dp[i][j-1]+1 //i后面插入字符 word2[j]dp[i][j]=dp[i-1][j]+1 //删除word1[i]dp[i][j]=dp[i-1][j-1]+1 //替换:word1[i]替换为word2[j]因此: dp[i][j]=min(dp[i][...原创 2021-12-15 16:08:33 · 755 阅读 · 0 评论 -
leetcode44.通配符匹配(困难)
同leetcode10.正则表达式类似:https://blog.youkuaiyun.com/zhangjiaji111/article/details/120973254思路:动态规划。具体:dp[i][j]表示s[0…i]与p[0…j]是否匹配,匹配为true,反之为false。(1)当p[j]!=’ *‘时(当p[j]==’?’||s[i]==p[j])dp[i][j] = dp[i - 1][j - 1];(2)当p[j] ==’ * '时:如果 * 代表出现空串,dp[i][j]=dp...原创 2021-12-10 15:18:21 · 467 阅读 · 0 评论 -
leetcode338.比特位计数(简单)
方法一:一个数一个数枚举 ------->O(nlogn)class Solution {public: vector<int> countBits(int n) { vector<int> ans(n + 1); for (int i = 0; i < n + 1; ++i) { int tmp = i; while(tmp) { an...原创 2021-12-09 22:33:22 · 466 阅读 · 0 评论 -
leetcode62.不同路径(中等)
思路一:记忆化搜索class Solution {public: unordered_map<int, int> ump; int get_index(int x, int y, int n) { return x * n + y; } int dfs(int x, int y, int m, int n) { int tmp = get_index(x, y, n); if (ump.count(tmp...原创 2021-12-08 23:10:29 · 315 阅读 · 0 评论 -
leetcode70.爬楼梯(简单,快速幂)
思路一:记忆化dfsclass Solution {public: unordered_map<int, int> ump; int dfs(int n) { if (n == 1) return 1; if (n == 2) return 2; if (ump.count(n)) return ump[n]; ump[n] = dfs(n - 2) + dfs(n - 1); return ..原创 2021-12-08 21:43:30 · 617 阅读 · 0 评论 -
leetcode322.零钱兑换(中等)
思路一:DP,类比完全背包dp[i][j]表示前i个硬币 金额j 所需要的最少硬币数dp[i][j]=min(dp[i-1][j],dp[i][j-coins[i]]+1);边界:由于是取最小值,所以dp[-1][1…amount]设置为INT_MAX-1(防溢出)金额0时需要0个硬币,也就是dp[-1][0]=0(有一个不为正无穷)!!!class Solution {public: int coinChange(vector<int>& coins, int...原创 2021-11-24 21:15:18 · 347 阅读 · 0 评论 -
leetcode221.最大正方形(中等)
自己的思路:单调栈 有问题具体: 2 2就翻车了。。。单调栈的思路是错的,最大正方形不一定最大在第一个小于他的位置,后面可能有更优的与leetcode85.最大矩形进行对比原创 2021-11-05 10:01:57 · 196 阅读 · 0 评论