leetcode 经典动态规划DP算法题目(思路、方法、code)

leetcode买卖股票问题(思路方法code) 一文解决Leetcode买卖股票问题 对于前3个问题,均采用了比较巧妙的解法。由于第4个问题具有非常强的泛型,因此采用了DP,第4个问题的dp如果理解的话,实际上只需要稍加修改状态便可以用该dp思路应用于所有的6个题中。在后两个问题便是基于该思路dp解决的。 文章目录一文解决Leetcode买卖股票问题[121. 买卖股票的最佳时机](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/)[122. 买卖股票的最佳时机 II]( 阅读详情

leetcode 经典动态规划DP算法题目(思路、方法、code)

动态规划最重要的在于设计DP数组,找到相应的动态转移方程

70. 爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

**注意:**给定 n 是一个正整数。

分析:这个问题,可以看青蛙跳台阶(递归与数学归纳),实际上就是斐波那契数列的变体

在上述中,采用了递归或者正向遍历的方法,实际上动态规划就是一种正向遍历的方法。如果采用递归时,由于f(n)=f(n-1)+f(n-2),故直接递归即可,但是仔细思考,如果用该方法,计算f(n-1)时计算了f(n-2),而计算f(n)时又计算了f(n-2),因此存在大量的重复计算。故在此便考虑用一个数组存储对应的函数值,这便是动态规划思想。

令f(n)表示到达n阶的楼顶的方法数,则f(n)=f(n-1)+f(n-2),正向计算即可。

class Solution {
   
   
public:
    int climbStairs(int n) 
    {
   
   
         vector<int> dp(n+1);
         dp[0]=1;dp[1]=1;
         for(int i=2;i<=n;i++)
            dp[i]=dp[i-1]+dp[i-2];
        return dp[n];
    }
};
198. 打家劫舍

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。

示例 1:
输入: [1,2,3,1]
输出: 4
解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
     偷窃到的最高金额 = 1 + 3 = 4 。

示例 2:
输入: [2,7,9,3,1]
输出: 12
解释: 偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
     偷窃到的最高金额 = 2 + 9 + 1 = 12

分析:由于相邻的房间不能同时选择,因此在第k个房间时,有两种情况

  • 如果选取了第k个房间,说明第k-1个房间一定不能选,那说明这种情况的最大金额应该是前k-2个房间的最大金额加上第k个房间的金额
  • 如果没有选取第k个房间,说明这种情况的最大金额实际上就是前k-1个房间的最大金额
  • 因此,如果令 d p [ i ] dp[i] dp[i] 表示从0 到 $i $ 房间能盗窃的最高金额,动态转移方程则为 d p [ i ] = m a x ( d p [ i − 2 ] + a [ i ] , d p [ i − 1 ] ) dp[i]=max(dp[i-2]+a[i],dp[i-1]) dp[i]=max(dp[i2]+a[i],dp[i1]) ,其中 a [ i ] a[i] a[i]表示第i个房间的金额

根据此,可以遍历,最终结果应该为 d p [ n − 1 ] dp[n-1] dp[n1]

class Solution {
   
   
public:
    int rob(vector<int>& nums) 
    {
   
   
        int length=nums.size();
        if(length==0) return 0;
        if(length==1) return nums[0];
        vector<int> dp(length+1);
        dp[0]=nums[0];
        dp[1]=max(nums[0],nums[1]);
        for(int i=2;i<length;i++)
        {
   
   
            dp[i]=max(dp[i-2]+nums[i],dp[i-1]);
        }
        return dp[length-1];
    }
};
213. 打家劫舍 II

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。

示例 1:
输入: [2,3,2]
输出: 3
解释: 你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2, 因为他们是相邻的。

示例 2:
输入: [1,2,3,1]
输出: 4
解释: 你可以先偷窃 1 号房屋(金额 = 1),然后偷窃 3 号房屋(金额 = 3)。
     偷窃到的最高金额 = 1 + 3 = 4

分析:这个题与上一个题的区别在于,房屋是环形的,这意味着,第一个房间和最后一个房间不能同时偷窃。这就意味着,**将原来的问题转化为两个子问题:偷窃1 ~ n-1个房间的最大值以及偷窃 2~n 个房间的最大值。最终,取二者的最大值即为解。**因此可以对上一个问题进行两次dp即可。

class Solution {
   
   
public:
    int rob(vector<int>& nums) 
    {
   
   
        int length=nums.size();
        if(length==0) return 0;
        if(length==1) return nums[0];
        vector<int> dp(length+1);
        dp[0]=nums[0];
        dp[1]=max(nums[0],nums[1]);
        for(int i=2;i<length-1;i++) //先对前n-1进行DP
        {
   
   
            dp[i]=max(dp[i-2]+nums[i],dp[i-1]);
        }
        int result=dp[length-2]; //存储其值
        dp[0]=0;dp[1]=nums[1];
        for(int i=2;i<length;i++)  //对后n-1进行DP
        {
   
   
            dp[i]=max(dp[i-2]+nums[i],dp[i-1]);
        }
        //取最大值即可
        result=max(result,dp[length-1]);
        return result;
    }
};
337. 打家劫舍 III

在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。

计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。

示例 1:
输入: [3,2,3,null,3,null,1]

     3
    / \
   2   3
    \   \ 
     3   1

输出: 7 
解释: 小偷一晚能够盗取的最高金额 = 3 + 3 + 1 = 7.

示例 2:
输入: [3,4,5,1,3,null,1]

     3
    / \
   4   5
  / \   \ 
 1   3   1

输出: 9
解释: 小偷一晚能够盗取的最高金额 = 4 + 5 = 9.

分析:每个节点可选择偷或者不偷两种状态,根据题目意思,相连节点不能一起偷,因此父结点如果偷,则两个字节点就不能偷,父结点如果不偷,则子节点可以偷。注意这里说的是可以而不是一定,只需要父结点不偷的情况下两个子节点能够拿出最多的钱即可。因此有了递归的想法。

  • 当前节点选择不偷:当前节点能偷到的最大钱数 = 左孩子能偷到的最大钱 + 右孩子能偷到的最大钱
  • 当前节点选择偷:当前节点能偷到的最大钱数 = 左孩子选择自己不偷时能得到的钱 + 右孩子选择不偷时能得到的钱 + 当前节点的钱数
  • 考虑到在python中常用的返回多值的函数,在此处用了pair来存储结果,其中pair的第一个表示当前节点不偷获得的最大钱,pair的第二个表示当前节点偷的话获得的最大钱,根据此,便可以将上述逻辑轻松地表达出来。
class Solution {
   
   
public:
    int rob(TreeNode* root) 
	{
   
   
		pair<int,int> result=rob_helper(root);
		return max(result.first,result.second);
    }
    pair<int,int> rob_helper(TreeNode* root)
    {
   
   
    	pair<int,int> root_result;
    	pair<int,int> root_left;
    	pair<int,int> root_right;
    	if(root==NULL) return root_result;	
    	else
    	{
   
   
    		root_left=rob_helper(root->left);
    		root_right=rob_helper(root->right);
		}
			
  root_result.first=max(root_left.first,root_left.second)+max(root_right.first,root_right.second);
		root_result.second=root_left.first+root_right.first+root->val;
		return root_result;
	}
};
53. 最大子序和

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6

分析:

动态规划法:动态规划的关键,就是设置dp变量,找到动态转移方程

对于该题而言,由于需要找连续子数组,因此设置 d p dp dp变量时,必须考虑如何设置才能够将连续考虑在内。在此用 d p [ i ] dp[i]

最佳解决Maven同一依赖多版本共存问题,重复依赖(同一个jar包,多个版本)-maven-shade-plugin 公司的历史项目在导出功能上引用的是poi-3.12版本,后续再做word模板导出功能时用到了poi-3.15版本,升级完后发现项目的很多导出功能都瘫痪了。用旧版本,新功能无法使用;用新版本,旧功能瘫痪,且整改的工作量比较大。使用maven-shade-plugin,将某个版本的依赖名称进行修改,重新引入即可。 阅读详情

相关推荐

【踩坑记录】pandas.to_sql 报 “‘Engine‘ object has no attribute ‘cursor‘”,最后竟然是环境问题

摘要 本文记录了使用pandas+SQLAlchemy+pymysql将数据写入MySQL时遇到的"Engine对象无cursor属性"错误及其解决方案。问题表现为to_sql方法将SQLAlchemy引擎误认为普通DBAPI连接,导致调用cursor()方法失败。经排查发现,这是由于pandas/SQLAlchemy环境损坏所致,而非代码问题。最终通过完全卸载并重新安装pandas(≥2.1)、SQLAlchemy(≥2.0)和pymysql解决了该问题。文章还建议将遗留的read_s

每日出拳老爷子的博客 318

DP-LeetCode1143. 最长公共子序列(Python)

1、题目描述 2、代码详解 自下向上 class Solution(object): # Modify the original triangle, bottom-up def minimumTotal(self, triangle): """ :type triangle: List[List[int]] :rtype: int """ if not triangle: return for i in range(len(triangle) - 2, -

Qt 4.8.6安装与搭建开发环境

Qt 4.8.6安装与搭建开发环境,内含详细搭建环境的步骤。

leetcode学习一之动态规划DP

leetcode学习一之动态规划DP) 1.最大子序和(leetcode 53 S.) 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 常规: class Solution { public int maxSubArray(int[] nums) { //定义和 int

konghuan521的博客 616

leetcode 常规dp问题通解思路

leetcode 最长递增子序列2. 一组整数对能够构成的最长链3. 最长摆动子序列二、使用步骤1.引入库2.读入数据总结 # 最长递增子序列 ## 1. 最长递增子序列 leetcode 300 class Solution: def lengthOfLIS(int[] nums): dp=[1]*len(nums) for i in range(1,len(nums)): for j in range(i): if nums[i]&gt

weixin_39940694的博客 3218

LeetCode-【总结】dp问题小结

dp分类 dp问题大致分为: 线性dp 背包dp 序列dp 区间dp 状压dp 数位dp …… 背包dp 参见:自己的背包dp总结 序列dp 经典问题:最长上升子序列、最长公共子序列 参见:自己的LIS、LCS总结 一般时间复杂度 O(nlogn) 或 O(n^2) 例如,LCS中,dp[i][j] 一般定义为 两个序列或字符串中分别在第i、j个位置结尾的序列对应的 最长公共子序列长度 难一点的问题会涉及到 找出该最长公共子序列 区间dp 一般dp[i][j]表示一个序列中s[i]~s[j]这个区间的答

weixin_43563311的博客 1756

LeetCode----->dp系列

198. 打家劫舍 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。 输入: [1,2,3,1]输出: 4解释: 偷窃 1 号房屋 (金额 = 1)...

weixin_30918415的博客 317

LeetCode | 图文详细描述动态规划DP算法经典题型

F(0)=0F(1)=1F(n)=F(n−1)+F(n−2)(当 n≥2)例:n = 211 是斐波那契数列的第 2 个数字。n = 555 是斐波那契数列的第 5 个数字。

weixin_44649780的博客 2797

力扣LeetCode 动态规划——dp code心经

动态规划 == 由于我开了picgo 直接从typora里面复制过来图片链接会被拦截地址,所以等我想想办法…== Alchemist (dp 填表练习地址) [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cy8G8fHj-1633874597420)(https://i.loli.net/2021/10/06/7JsHx1ilO3bLvQB.png)] 1. 判断子序列 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h500r2gv-1

m0_50176535的博客 420

【GitHub项目推荐--LeetCodeAnimation:用动画的形式呈现LeetCode题目思路

​​ 是一个创新的开源项目,由MisterBooo(吴师兄)创建,致力于用动画的形式演示LeetCode题目的解题思路。该项目通过直观的动画可视化,帮助开发者更好地理解和掌握算法数据结构的核心概念,让抽象的算法变得生动易懂。🔗 ​GitHub地址🚀 ​核心价值​:动画演示 · 算法可视化 · 学习辅助 · 直观理解​项目背景​:​学习痛点​:解决算法学习抽象难懂的问题​视觉学习​:利用动画提升学习效果和理解深度​创新教学​:创新的算法教学方法​长期规划​:3-4年完成所有题目动画化​。

j8267643的博客 1049

LeetCode---区间DP

简介: 区间DPleetcode上也有体现(主要是合并石子类型),本文就leetcode上出现的区间DP做一个总结。 题目原型: 5301 石子合并 0x50「动态规划」例题 描述 设有N堆沙子排成一排,其编号为1,2,3,…,N(N<=300)。每堆沙子有一定的数量,可以用一个整数来描述,现在要将这N堆沙子合并成为一堆,每次只能合并相邻的两堆,合并的代价为这两堆沙子的数量...

sgh666666的博客 1187

一文搞懂从爬楼梯到最小花费(力扣70,746)

动态规划算法(Dynamic Programming)是一种解决多阶段决策过程最优化问题的方法。它将问题分解为相互重叠的子问题,并通过解决子问题来解决整个问题。这种方法通常用于具有重叠子问题和最优子结构性质的问题。动态规划的基本思想是将原问题分解为相互重叠的子问题,并在解决这些子问题时进行存储,以避免重复计算。通过这种方式,可以大大减少计算量,提高算法效率。动态规划算法通常涉及两个关键步骤:定义状态和状态转移方程。定义状态: 确定问题中的状态变量,并定义状态之间的关系。

Huahua_1223的博客 2453

动态规划】【入门 DP】—118.杨辉三角

本文以杨辉三角为例介绍动态规划的基本应用。通过确定dp数组含义、推导递推公式(dp[i][j]=dp[i-1][j-1]+dp[i-1][j])并处理边界条件,实现了生成杨辉三角的算法。文章详细解析了动态规划的5个关键步骤,并提供了一个Python实现,重点处理了不等长二维数组的初始化和边界元素问题。最后补充了Python中定义不等长二维数组的方法。该解法时间复杂度O(),空间复杂度O(1)(不考虑输出空间)

weixin_50512050的博客 1080

动态规划::线性DP」股票问题合集 / LeetCode 121|122|123|188 (C++)

我们已经了解过了线性DP: 更进一步,我们来解决非常经典的线性DP问题系列:买卖股票。

dakingffo的博客 1160

动态规划】【入门 DP】—70. 爬楼梯

动态规划是一种通过分解问题、存储子问题解来提高效率的算法。本文以LeetCode 70题"爬楼梯"为例,讲解动态规划的核心思路:定义dp[i]表示到达第i阶的方法数,状态转移方程为dp[i]=dp[i-1]+dp[i-2],并给出Python实现代码。同时补充了Python中列表、数组的定义与区别,强调动态规划需要长期练习来掌握状态转移方程的构建技巧。解题步骤包括确定状态、推导转移方程、初始化边界条件和验证dp数组的正确性。

weixin_50512050的博客 712

新坑 Leet Code DP动态规划)题解总和

毕业老,挖新坑,同学推荐了一个Leet Code OJ给我,之前搞ACM我最喜欢做DP题,所以对于新OJ,我想说的是,DP题就交给我吧。题目题解没有顺序,要查某题可以自行搜索,我还未解决的可以留言提醒我去搞定。顺带一提我这次做题准备全用JAVA来做。 P368. Largest Divisible Subset 题解:题目大意为一个非负数字集合,没有重复的数字。求一个最长的子集,子集中

1212

leetcode热题100.打家劫舍(动态规划进阶)

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。示例 1:示例 2:这是动态规划中的典型的“选与不选”的问题我们先讨论一般的情况,对于小偷而言,在偷取的过程中,每面临一个房子,小偷都有选和不选两种选择。对于小偷而言,此时的最优解是从两种情况中选一种,由这样的情况我们定

qq_51118755的博客 788

算法比赛】2020 力扣杯!Code Your Future 春季全国编程大赛

这个比赛,除了最后一题,其他四题其实没啥难度。 第一题:字符串操作。 第二题:模拟。 第三题:分析。 第四题:DP。 详细题解如下。 1.重新格式化字符串(Reformat the String) AC代码(C++) 2.点菜展示表(Display Table of Food Orders in A Restaurant) AC代码(C+...

Mikchy的博客 2056

Leetcode练习题:动态规划

Leetcode练习题:动态规划问题描述解题思路代码实现反思与收获问题描述解题思路代码实现反思与收获问题描述解题思路代码实现反思与收获问题描述解题思路代码实现反思与收获问题描述解题思路代码实现反思与收获问题描述解题思路代码实现反思与收获问题描述解题思路代码实现反思与收获问题描述解题思路代码实现反思与收获问题描述解题思路代码实现反思与收获 在进行这部分学习之前,我根本没有正式的学习过动态规划,遇到动态规划的题更是完全做不出来,即使我看别人解题的代码,也很难理解dp是个什么意思。但是学习了之后,了解了动态规划

weixin_43869937的博客 1359

LeetCode、746. 使用最小花费爬楼梯【简单,动态规划 线性DP

博主介绍:✌目前全网粉丝2W+,csdn博客专家、Java领域优质创作者,博客之星、阿里云平台优质作者、专注于Java后端技术领域。涵盖技术内容:Java后端、算法、分布式微服务、中间件、前端、运维、ROS等。博客目录索引(持续更新)b站-Coder长路。

每个人都是独一无二的,把握好自己的节奏,跟着自己的心走。 1144

【力扣刷题】Day27——DP专题

【力扣刷题】Day27——DP专题

涛涛的个人博客 1569
上一篇: leetcode 经典哈希表与字符串题目(思路、方法、code)
下一篇: leetcode 经典宽搜BFS深搜DFS题目(思路、方法、code)
coding丁
博客等级 码龄8年 382粉丝 147原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值