代码随想录刷题笔记 Day 53 买卖股票的最佳时机 No.121 | 买卖股票的最佳时机 No.122

本文主要是介绍代码随想录刷题笔记 Day 53 买卖股票的最佳时机 No.121 | 买卖股票的最佳时机 No.122,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • Day 53
      • 01. 买卖股票的最佳时机(No. 121)
        • <1> 题目
        • <2> 笔记
        • <3> 代码
      • 02. 买卖股票的最佳时机(No. 122)
        • <1> 题目
        • <2> 笔记
        • <3> 代码

Day 53

01. 买卖股票的最佳时机(No. 121)

题目链接

代码随想录题解

<1> 题目

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

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

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

示例 1:

输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

示例 2:

输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。

提示:

  • 1 <= prices.length <= 105
  • 0 <= prices[i] <= 104
<2> 笔记

提供一个数组,其中包含每天这支股票的价格,选择一天买入股票,再选择一天卖出股票,问最大能获得的利润是多少。

之前在贪心算法章节做到过的 买卖股票的最佳时机II 中可以买卖多次不同,本题只能进行 一次 买卖。

(1). 贪心思路

本题最容易想出的思路还是贪心思路,也就是选择最便宜的一天买入,最贵的一天卖出:

定义一个 low 来存储卖的最便宜的股票价格,循环遍历数组,查找哪一天卖出最便宜:

class Solution {public int maxProfit(int[] prices) {int low = Integer.MAX_VALUE;int res = 0;for (int i : prices) {low = Math.min(low, i); // 从 0 - i 最便宜的股票是哪一个res = Math.max(res, i - low); // 卖出股票}return res;}
}

很多朋友可能会对 lowres 赋值的顺序有疑惑,题目中不是说不能再某一天同时买入和卖出吗?如果将求最小的放在前面,那就可能会出现同一天买入和卖出的情况。但本题中其实求得是 最大值,如果说是同一天买入和同一天卖出的情况是最优解的话,那说明这个情况是 无法盈利 的,否则后续一定有更大的值可以将其覆盖。

(2). 动态规划思路

与贪心沿着固定的路径进行不同,动态规划其实更偏向于穷举,所以本题的动规解法的时间肯定是要长于贪心的。

首先来明确本题中的 状态 是什么,是在某一天通过买卖股票所持有的金钱,但为了描述这个状态,会出现两种情况:

  1. 当前处于买入的状态,也就是手中还持有股票,持有的金钱为 负数,因为此时只有支出
  2. 当前处于卖出的状态,手中的股票已经被卖出,持有的金钱为 正数

需要注意的是,某一天处于的是 买入 或者 卖出状态,而不是说股票是在这一天买入或者卖出的。

首先来定义 dp 数组,因为要存储某一天的两种状态,所以 dp 数组一定是一个二维数组

  • dp[i][0] 表示当前处于卖出的状态所持有的金钱
  • dp[i][1] 表示当前处于买入的状态所花费的金钱

再来确定递推公式,如果当前处于卖出的状态,说明股票是在今天被卖出,或者说 在昨天就已经处于被卖出的状态,所以:

dp[i][0] = Math.max(dp[i - 1][0], prices[i] + prices[1]);

对于当前的买入状态,是要在昨天的买入状态和今天的买入状态取一个最优解,所以:

dp[i][1] = Math.max(dp[i - 1][1], -prices[i]);

由此可以写出本题的代码。

<3> 代码
class Solution {public int maxProfit(int[] prices) {int[][] dp = new int[prices.length][2];dp[0][0] = 0; // 不持有股票的状态dp[0][1] = -prices[0]; // 买入的状态for (int i = 1; i < prices.length; i++){dp[i][0] = Math.max(dp[i - 1][0], prices[i] + dp[i - 1][1]); // 昨天卖出和今天卖出两种选择dp[i][1] = Math.max(dp[i - 1][1], -prices[i]);}return dp[prices.length - 1][0];}
}

02. 买卖股票的最佳时机(No. 122)

题目链接

代码随想录题解

<1> 题目

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

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

返回 你能获得的 最大 利润

示例 1:

输入:prices = [7,1,5,3,6,4]
输出:7
解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3 。
总利润为 4 + 3 = 7 。

示例 2:

输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
总利润为 4 。

示例 3:

输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 交易无法获得正利润,所以不参与交易可以获得最大利润,最大利润为 0 。

提示:

  • 1 <= prices.length <= 3 * 104
  • 0 <= prices[i] <= 104
<2> 笔记

(1). 回顾贪心解法

本题的贪心解法还是比较简单的,就是先买入一个股票,如果发现降价就直接替换,发现涨价则直接卖出,此时就能保证利润是最多的;感兴趣的话可以看一下我这篇博客
代码随想录刷题笔记 DAY 31 | 买卖股票的最佳时机 II No.122 | 跳跃游戏 No.55 | 跳跃游戏 II No.45

class Solution {public int maxProfit(int[] prices) {int res = 0;int pre = prices[0]; // 记录昨天的金钱for (int i = 1; i < prices.length; i++) {if (prices[i] > pre) {// 说明今天的股价升高了 卖出并且将今天的买入res += prices[i] - pre;   }pre = prices[i];}return res;}
}

(2). 动态规划解法

和上一题不同的是,本题可以买入和卖出多次了,但是 状态 还是不变的,即某一天 持有 或者 不持有 股票获取的最多金钱。

仍然选取和上一题相同的 dp 数组,即 dp[i][0] 表示当天不持有股票获取的最大金额;dp[i][1] 表示当天持有股票的时候的最多金钱。

对于 dp[i][0] 来说和上一题相同,可以选择今天卖出或者之前卖出的最优解,即

dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);

但对于 dp[i][1] 则不同,因为本次可以买卖多次,所以 dp[i][1]的值不止是可以通过未卖过的状态推导出来,同时也可以通过卖出的状态来推导出来

  • 第一个选择就是不购买今天的股票,也就是 dp[i - 1][1] 即昨天持有股票的情况
  • 第二个选择就是购入今天的股票
    • 可以选择在昨天卖出的情况下购入股票,也就是 dp[i - 1][0] - prices[i]
    • 同时也可以选择在昨天还持有股票的情况下购入股票,即 dp[i - 1][1] - prices[i]

但是对于第 i 天来说 dp[i][0] 是一定 大于等于 dp[i - 1][1] 的,因为 dp[i][0] 在花费最优的基础上还有售出的部分(也可能不售出),所以最终值肯定是大于等于 dp[i][1] 的,所以递推公式从求以上三个公式的最大值变为这样:

dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);

写出代码

<3> 代码
class Solution {public int maxProfit(int[] prices) {int[][] dp = new int[prices.length][2];dp[0][0] = 0; // 选择卖出的情况dp[0][1] = -prices[0]; // 手中还持有股票的情况for (int i = 1; i < prices.length; i++) {dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);}return dp[prices.length - 1][0];}
}

1

这篇关于代码随想录刷题笔记 Day 53 买卖股票的最佳时机 No.121 | 买卖股票的最佳时机 No.122的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/819439

相关文章

python实现pdf转word和excel的示例代码

《python实现pdf转word和excel的示例代码》本文主要介绍了python实现pdf转word和excel的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一、引言二、python编程1,PDF转Word2,PDF转Excel三、前端页面效果展示总结一

在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码

《在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码》在MyBatis的XML映射文件中,trim元素用于动态添加SQL语句的一部分,处理前缀、后缀及多余的逗号或连接符,示... 在MyBATis的XML映射文件中,<trim>元素用于动态地添加SQL语句的一部分,例如SET或W

使用C#代码计算数学表达式实例

《使用C#代码计算数学表达式实例》这段文字主要讲述了如何使用C#语言来计算数学表达式,该程序通过使用Dictionary保存变量,定义了运算符优先级,并实现了EvaluateExpression方法来... 目录C#代码计算数学表达式该方法很长,因此我将分段描述下面的代码片段显示了下一步以下代码显示该方法如

python多进程实现数据共享的示例代码

《python多进程实现数据共享的示例代码》本文介绍了Python中多进程实现数据共享的方法,包括使用multiprocessing模块和manager模块这两种方法,具有一定的参考价值,感兴趣的可以... 目录背景进程、进程创建进程间通信 进程间共享数据共享list实践背景 安卓ui自动化框架,使用的是

SpringBoot生成和操作PDF的代码详解

《SpringBoot生成和操作PDF的代码详解》本文主要介绍了在SpringBoot项目下,通过代码和操作步骤,详细的介绍了如何操作PDF,希望可以帮助到准备通过JAVA操作PDF的你,项目框架用的... 目录本文简介PDF文件简介代码实现PDF操作基于PDF模板生成,并下载完全基于代码生成,并保存合并P

SpringBoot基于MyBatis-Plus实现Lambda Query查询的示例代码

《SpringBoot基于MyBatis-Plus实现LambdaQuery查询的示例代码》MyBatis-Plus是MyBatis的增强工具,简化了数据库操作,并提高了开发效率,它提供了多种查询方... 目录引言基础环境配置依赖配置(Maven)application.yml 配置表结构设计demo_st

SpringCloud集成AlloyDB的示例代码

《SpringCloud集成AlloyDB的示例代码》AlloyDB是GoogleCloud提供的一种高度可扩展、强性能的关系型数据库服务,它兼容PostgreSQL,并提供了更快的查询性能... 目录1.AlloyDBjavascript是什么?AlloyDB 的工作原理2.搭建测试环境3.代码工程1.

Java调用Python代码的几种方法小结

《Java调用Python代码的几种方法小结》Python语言有丰富的系统管理、数据处理、统计类软件包,因此从java应用中调用Python代码的需求很常见、实用,本文介绍几种方法从java调用Pyt... 目录引言Java core使用ProcessBuilder使用Java脚本引擎总结引言python

Java中ArrayList的8种浅拷贝方式示例代码

《Java中ArrayList的8种浅拷贝方式示例代码》:本文主要介绍Java中ArrayList的8种浅拷贝方式的相关资料,讲解了Java中ArrayList的浅拷贝概念,并详细分享了八种实现浅... 目录引言什么是浅拷贝?ArrayList 浅拷贝的重要性方法一:使用构造函数方法二:使用 addAll(

JAVA利用顺序表实现“杨辉三角”的思路及代码示例

《JAVA利用顺序表实现“杨辉三角”的思路及代码示例》杨辉三角形是中国古代数学的杰出研究成果之一,是我国北宋数学家贾宪于1050年首先发现并使用的,:本文主要介绍JAVA利用顺序表实现杨辉三角的思... 目录一:“杨辉三角”题目链接二:题解代码:三:题解思路:总结一:“杨辉三角”题目链接题目链接:点击这里