本文主要是介绍代码随想录刷题笔记 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;}
}
很多朋友可能会对
low
和res
赋值的顺序有疑惑,题目中不是说不能再某一天同时买入和卖出吗?如果将求最小的放在前面,那就可能会出现同一天买入和卖出的情况。但本题中其实求得是 最大值,如果说是同一天买入和同一天卖出的情况是最优解的话,那说明这个情况是 无法盈利 的,否则后续一定有更大的值可以将其覆盖。
(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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!