算法日记 33 day 动态规划(打家劫舍,股票买卖)

今天来看看动态规划的打家劫舍和买卖股票的问题。

上题目!!!!

题目:打家劫舍

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

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

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

题目分析:

        对于每一房间其实只有两种状态,偷或不偷,而且这个状态也取决于之前偷没偷。五部曲分析。

dp[i]:小偷到第i间放的最大金额

i的两种状态(偷,不偷)

不偷:dp[i]=dp[i-1]

偷:dp[i]=dp[i-2]

dp[0]=nums[0]    dp[1]=max(nums[0],nums[1])

public class Solution {
    public int Rob(int[] nums) {
        if(nums.Length==0) return 0;
        if(nums.Length==1) return nums[0];
        int[] dp=new int[nums.Length];
        dp[0]=nums[0];
        dp[1]=Math.Max(nums[0],nums[1]);
        for(int i=2;i<nums.Length;i++){
            dp[i]=Math.Max(dp[i-2]+nums[i],dp[i-1]);
        }
        return dp[nums.Length-1];
    }
}

 题目:打家劫舍 2

213. 打家劫舍 II - 力扣(LeetCode)

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

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

题目分析:

        房子围城一圈,那么对于首尾的房子而言,我们只能偷一个,其他的房间呢则尽量偷。本质上就和上一题一样了,无非是偷的时候划分一下区间即可,其他部分完全一样。

public class Solution {
    public int Rob(int[] nums) {
        if(nums.Length==0) return 0;
        if(nums.Length==1) return nums[0];
        int res1=RobRange(nums,0,nums.Length-2);
        int res2=RobRange(nums,1,nums.Length-1);
        return Math.Max(res1,res2);

    }
    public int RobRange(int[] nums,int start,int end){
        if (end == start) return nums[start];
        int[] dp=new int[nums.Length];
        dp[start]=nums[start];
        dp[start+1]=Math.Max(nums[start],nums[start+1]);
        for(int i=start+2;i<=end;i++){
            dp[i]=Math.Max(dp[i-2]+nums[i],dp[i-1]);
        }
        return dp[end];
    }
}

题目:打家劫舍 III

 337. 打家劫舍 III - 力扣(LeetCode)

小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 。

除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。

给定二叉树的 root 。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。

题目分析: 

        房子的排列变成了树形结构,那么不触发警报意味着,如果我们偷了一个结点,那么他的两个子节点都不能偷。

        其实结点的状态任然是两种偷或者不偷。但是我们要偷取的金额最大,一定要考虑不偷这个的情况下,他的左右子节点偷不偷呢。所以需要将左右孩子的偷不偷的最大金额返回给父节点,那么对于这个树的遍历只能使用后序遍历的方式。

public class Solution {
    public int Rob(TreeNode root) {
        int[] res=RobTrue(root);
        return Math.Max(res[1],res[0]);
    }
    public int[] RobTrue(TreeNode root){
        if(root==null) return new int[2]{0,0};

        int[] leftDp=RobTrue(root.left);
        int[] rightDp=RobTrue(root.right);

        //下标为0记录不偷该节点所得到的的最大金钱,下标为1记录偷该节点所得到的的最大金钱。
        int res1=root.val+leftDp[0]+rightDp[0];//偷这个结点加上不偷左右孩子的最大值
        int res2=Math.Max(leftDp[0],leftDp[1])+Math.Max(rightDp[0],rightDp[1]);//不偷这个结点,就考虑左右孩子要不要偷

        return new int[]{res2,res1};
    }
}

题目:买卖股票的最佳时机

121. 买卖股票的最佳时机 - 力扣(LeetCode)

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

题目分析:

        这一题可以用暴力和贪心的方法解决。

暴力,依次枚举股票价格,并且找出最大差值作为结果即可。

贪心的想法很自然就是取最左最小值,取最右最大值,那么得到的差值就是最大利润。

两者差不多。

public class Solution {
    public int MaxProfit(int[] prices) {
        int min=int.MaxValue;
        int res=0;
        for(int i=0;i<prices.Length;i++){
            min=Math.Min(prices[i],min);
            res=Math.Max(res,prices[i]-min);
        }
        return res;
    }
}

动态规划:

        考虑股票的状态,其实就只有持有和不持有两种状态。注意这里的持有和不持有并不是买入卖出的意思。来看看dp数组的解释。

dp[i][0]:在第i天这支股票在我手上持有的最大金额(利润)

dp[i][1]:在第i天这支股票不在我手上持有的最大金额(利润)

注意两个的区别,因为这个持有和不持有他需要考虑前一天的状态,也就是说在这一天之前,这个股票我可能已经买入或者卖出了。这个很重要。

递推公式:

持有股票(1.在这一天之前我就持有了 2,之前我没有,但是今天买入后持有了)

1.dp[i-1][0]   2.-price[i]

 dp[i][0]=max(dp[i-1][0],-price[i])

不持有股票(1.在这一天之前我就没有了 2,之前我有,但是今天卖了后就没有了)

1.dp[i-1][1]   2.dp[i-1][0]+price[i]

 dp[i][0]=max(dp[i-1][1] ,dp[i-1][0]+price[i])

初始化就很好理解了,那么来看看代码

public class Solution {
    public int MaxProfit(int[] prices) {
        int[,] dp=new int[prices.Length,2];
        dp[0,0]=-prices[0];//持有这个股票
        dp[0,1]=0;//不持有这个股票

        for(int i=1;i<prices.Length;i++){
            dp[i,0]=Math.Max(-prices[i],dp[i-1,0]);
            dp[i,1]=Math.Max(dp[i-1,0]+prices[i],dp[i-1,1]);
        }
        return Math.Max(dp[prices.Length-1,0],dp[prices.Length-1,1]);
    }
}

 题目:买卖股票的最佳时机II

122. 买卖股票的最佳时机 II - 力扣(LeetCode)

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。

返回 你能获得的 最大 利润 。

题目分析:

         注意和上一题的区别,题目中的每一天意味着我可以多次买入卖出。但是上一题我只能操作一次。

        这里的dp的含义和上一题一样的,区别是dp的递推公式。

递推公式:

持有股票(1.在这一天之前我就持有了 2,(可能我已经卖出过了)之前我没有,但是今天买入后持有了)

1.dp[i-1][0]   2.dp[i-1][1]-price[i](上一天是不持有的状态)

 dp[i][0]=max(dp[i-1][0],dp[i-1][1]-price[i])

不持有股票(1.在这一天之前我就没有了 2,之前我有,但是今天卖了后就没有了)

1.dp[i-1][1]   2.dp[i-1][0]+price[i]

 dp[i][0]=max(dp[i-1][1] ,dp[i-1][0]+price[i])

public class Solution {
    public int MaxProfit(int[] prices) {
        int[,] dp=new int[prices.Length,2];
        dp[0,0]=-prices[0];//持有这个股票
        dp[0,1]=0;//不持有这个股票

        for(int i=1;i<prices.Length;i++){
            dp[i,0]=Math.Max(dp[i-1,1]-prices[i],dp[i-1,0]);
            dp[i,1]=Math.Max(dp[i-1,0]+prices[i],dp[i-1,1]);
        }
        return Math.Max(dp[prices.Length-1,0],dp[prices.Length-1,1]);
    }
}

 主要区别在于持有股票是需要考虑之前是否有卖出过,这一点在下面的题中很重要

题目:买卖股票的最佳时机III

123. 买卖股票的最佳时机 III - 力扣(LeetCode)

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

 题目分析:

        会看前面两题,第一题要求只能买入卖出1次,第二题能买入卖出无数次。而这一题最多两次,和上面两题一样,看看股票在第i天可能出现的状态。

第一次买入

第一次卖出

第二次买入

第二次卖出

那么dp数组的含义就很好理解了。

来看看递推公式,本质上和上面的题是一样的,无非就是买入卖出的时候需要考虑之前的状态,这一点和第二题一样。

达到dp[i][1]状态,有两个具体操作:

  • 操作一:第i天买入股票了,那么dp[i][1] = dp[i-1][0] - prices[i]
  • 操作二:第i天没有操作,而是沿用前一天买入的状态,即:dp[i][1] = dp[i - 1][1]

那么dp[i][1]究竟选 dp[i-1][0] - prices[i],还是dp[i - 1][1]呢?

一定是选最大的,所以 dp[i][1] = max(dp[i-1][0] - prices[i], dp[i - 1][1]);

同理dp[i][2]也有两个操作:

  • 操作一:第i天卖出股票了,那么dp[i][2] = dp[i - 1][1] + prices[i]
  • 操作二:第i天没有操作,沿用前一天卖出股票的状态,即:dp[i][2] = dp[i - 1][2]

所以dp[i][2] = max(dp[i - 1][1] + prices[i], dp[i - 1][2])

同理可推出剩下状态部分:

dp[i][3] = max(dp[i - 1][3], dp[i - 1][2] - prices[i]);

dp[i][4] = max(dp[i - 1][4], dp[i - 1][3] + prices[i]);

对于初始化而言,需要注意的是你可以在一天内多次买入卖出,因为price的长度可以为1。 

public class Solution {
    public int MaxProfit(int[] prices) {
        int[,] dp=new int[prices.Length,5];
        dp[0,0]=0;//0,不操作
        dp[0,1]=-prices[0];//1,第一次持有
        dp[0,2]=0;//2,第一次不持有
        dp[0,3]=-prices[0];//3,第二次持有
        dp[0,4]=0;//4,第二次不持有
        for(int i=1;i<prices.Length;i++){
            dp[i,1]=Math.Max(dp[i-1,1],-prices[i]);
            dp[i,2]=Math.Max(dp[i-1,1]+prices[i],dp[i-1,2]);
            dp[i,3]=Math.Max(dp[i-1,3],dp[i,2]-prices[i]);
            dp[i,4]=Math.Max(dp[i-1,4],dp[i-1,3]+prices[i]);
        }
        return Math.Max(dp[prices.Length-1,4],dp[prices.Length-1,2]);
    }
}

 

对于更详细的解析与其他语言的代码块,可以去代码随想录上查看。

代码随想录 (programmercarl.com)

已刷题目:110

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/923262.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python绘制太极八卦

文章目录 系列目录写在前面技术需求1. 图形绘制库的支持2. 图形绘制功能3. 参数化设计4. 绘制控制5. 数据处理6. 用户界面 完整代码代码分析1. rset() 函数2. offset() 函数3. taiji() 函数4. bagua() 函数5. 绘制过程6. 技术亮点 写在后面 系列目录 序号直达链接爱心系列1Pyth…

package.json中^1.x.x、~1.x.x、1.x.x有什么区别

目录 包版本号的语义化 包版本号的符号 举例 包版本号的语义化 在开始回答这个问题之前&#xff0c;先简单介绍一下包版本号的语义化。 在npm中&#xff0c;包的版本号通常遵循语义化版本规范&#xff08;Semantic Versioning&#xff09;&#xff0c;即采用 major.minor.p…

力扣hot100-->排序

排序 1. 56. 合并区间 中等 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 示例 1&#xff1a; 输…

一分钟学习数据安全——数据安全风险的系统化应对思路

数据是组织的重要资产&#xff0c;未经授权的数据访问可能导致数据泄露、数据篡改、隐私侵犯和合规风险等问题。企业可以通过数据访问控制来提高信息系统在数据全生命周期管理中的安全性。企业可以引入IAM系统&#xff0c;来控制身份来管理权限。通过对用户访问权限的管理和合适…

免费实用在线AI工具集合 - 加菲工具

免费在线工具-加菲工具 https://orcc.online/ 在线录屏 https://orcc.online/recorder 时间戳转换 https://orcc.online/timestamp Base64 编码解码 https://orcc.online/base64 URL 编码解码 https://orcc.online/url Hash(MD5/SHA1/SHA256…) 计算 https://orcc.online/h…

五种创建k8s的configMap的方式及configmap使用

configmap介绍 Kubernetes 提供了 ConfigMap 来管理应用配置数据&#xff0c;将配置信息从容器镜像中解耦&#xff0c;使应用更灵活、可移植。 1、基于一个目录来创建ConfigMap ​ 你可以使用 kubectl create configmap 基于同一目录中的多个文件创建 ConfigMap。 当你基于目…

ssm185大学学术交流论坛+vue(论文+源码)_kaic

摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于大学学术交流论坛当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了大学学术交流论坛的发展&#xff0c;它彻底…

构建 Java Web 应用程序:从 Servlet 到数据库交互(Eclipse使用JDBC连接Mysql数据库)

第 1 部分&#xff1a;环境设置 安装 Java Development Kit (JDK)&#xff1a;下载并安装 JDK。设置 IDE&#xff1a;安装并配置 IDE&#xff08;如 IntelliJ IDEA 或 Eclipse&#xff09;。安装数据库&#xff1a;下载并安装 MySQL 数据库。配置数据库&#xff1a;创建数据库…

C 语言面向对象

面向对象的基本特性&#xff1a;封装&#xff0c;继承&#xff0c;多态 1.0 面向过程概念 当我们在编写程序时&#xff0c;通常采用以下步骤&#xff1a; 1. 将问题的解法分解成若干步骤 2. 使用函数分别实现这些步骤 3. 依次调用这些函数 这种编程风格的被称作 面向过程…

aws服务--机密数据存储KMS(1)介绍和使用

在AWS(Amazon Web Services)中存储机密数据时,安全性和合规性是最重要的考虑因素。AWS 提供了多个服务和工具,帮助用户确保数据的安全性、机密性以及合规性。AWS Secrets Manager、KMS(Key Management Service)是推荐的存储机密数据的AWS服务和最佳实践。这里先看KMS。 …

ArcGIS应用指南:ArcGIS制作局部放大地图

在地理信息系统&#xff08;GIS&#xff09;中&#xff0c;制作详细且美观的地图是一项重要的技能。地图制作不仅仅是简单地将地理数据可视化&#xff0c;还需要考虑地图的可读性和美观性。局部放大图是一种常见的地图设计技巧&#xff0c;用于展示特定区域的详细信息&#xff…

【案例学习】如何使用Minitab实现包装过程的自动化和改进

Masimo 是一家全球性的医疗技术公司&#xff0c;致力于开发和生产各种行业领先的监控技术&#xff0c;包括创新的测量、传感器和患者监护仪。在 Masimo Hospital Automation 平台的助力下&#xff0c;Masimo 的连接、自动化、远程医疗和远程监控解决方案正在改善医院内外的护理…

【JavaEE初阶】多线程初阶下部

文章目录 前言一、volatile关键字volatile 能保证内存可见性 二、wait 和 notify2.1 wait()方法2.2 notify()方法2.3 notifyAll()方法2.4 wait 和 sleep 的对比&#xff08;面试题&#xff09; 三、多线程案例单例模式 四、总结-保证线程安全的思路五、对比线程和进程总结 前言…

【小白学机器学习33】 大数定律python的 pandas.Dataframe 和 pandas.Series基础内容

目录 0 总结 0.1pd.Dataframe有一个比较麻烦琐碎的地方&#xff0c;就是引号 和括号 0.2 pd.Dataframe关于括号的原则 0.3 分清楚几个数据类型和对应的方法的范围 0.4 几个数据结构的构造关系 list → np.array(list) → pd.Series(np.array)/pd.Dataframe 1 python 里…

《用Python画蔡徐坤:艺术与编程的结合》

简介 大家好&#xff01;今天带来一篇有趣的Python编程项目&#xff0c;用代码画出知名偶像蔡徐坤的形象。这个项目使用了Python的turtle库&#xff0c;通过简单的几何图形和精心设计的代码来展示艺术与编程的结合。 以下是完整的代码和效果介绍&#xff0c;快来试试看吧&…

OSG开发笔记(三十三):同时观察物体不同角度的多视图从相机技术

​若该文为原创文章&#xff0c;未经允许不得转载 本文章博客地址&#xff1a;https://blog.csdn.net/qq21497936/article/details/143932273 各位读者&#xff0c;知识无穷而人力有穷&#xff0c;要么改需求&#xff0c;要么找专业人士&#xff0c;要么自己研究 长沙红胖子Qt…

数据结构(Java版)第二期:包装类和泛型

目录 一、包装类 1.1. 基本类型和对应的包装类 1.2. 装箱和拆箱 1.3. 自动装箱和自动拆箱 二、泛型的概念 三、引出泛型 3.1. 语法规则 3.2. 泛型的优点 四、类型擦除 4.1. 擦除的机制 五、泛型的上界 5.1. 泛型的上界的定义 5.2. 语法规则 六、泛型方法 6.1…

ffmpeg 视频滤镜:高斯模糊-gblur

滤镜描述 gblur 官网地址 > FFmpeg Filters Documentation 这个滤镜会将视频变得模糊。 滤镜使用 参数 gblur AVOptions:sigma <float> ..FV.....T. set sigma (from 0 to 1024) (default 0.5)steps <int> ..FV.....T…

vue中路由缓存

vue中路由缓存 问题描述及截图解决思路关键代码及打印信息截图 问题描述及截图 在使用某一平台时发现当列表页码切换后点击某一卡片进入详情页后&#xff0c;再返回列表页时页面刷新了。这样用户每次看完详情回到列表页都得再重新输入自己的查询条件&#xff0c;或者切换分页到…

eclipse-git项目提示NO-HEAD

1、出现该问题的过程 本人在用eclipse拉取git代码&#xff0c;刚拉取完&#xff0c;可能还没来得及跟本地的分支合并&#xff0c;电脑就卡动了。无奈只能重启电脑&#xff0c;打开eclipse&#xff0c;maven项目后面就出现了xxx NO-HEAD的提示。 2、问题解决 根据错误提示&am…