Leetcode(122)——买卖股票的最佳时机 II

LeetCode算法题解(贪心)|LeetCode122. 买卖股票的最佳时机 II、LeetCoed55. 跳跃游戏、LeetCode45. 跳跃游戏 II 贪心算法,难点是如何找到局部最优,然后如何推到全局最优。 阅读详情

Leetcode(122)——买卖股票的最佳时机 II

题目

给你一个整数数组 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 。

提示:

  • 111 <= prices.length <= 3∗1043 * 10^43∗104
  • 000 <= prices[i] <= 10410^4104

题解

方法一:贪心

思路

​​  因为由于股票的购买没有限制,因此整个问题等价于寻找 xxx 个不相交的区间 (li,ri](l_i,r_i](li​,ri​] 使得如下的等式最大化
∑i=1xa[ri]−a[li] \sum_{i=1}^{x} a[r_i]-a[l_i] i=1∑x​a[ri​]−a[li​]

​​  其中 lil_ili​ 表示在第 lil_ili​ 天买入,rir_iri​ 表示在第 rir_iri​ 天卖出。

​​  同时我们注意到对于 (li,ri](l_i,r_i](li​,ri​] 这一个区间贡献的价值 a[ri]−a[li]a[r_i]-a[l_i]a[ri​]−a[li​],其实等价于 (li,li+1],(li+1,li+2],…,(ri−1,ri](l_i,l_i+1],(l_i+1,l_i+2],\ldots,(r_i-1,r_i](li​,li​+1],(li​+1,li​+2],…,(ri​−1,ri​] 这若干个区间长度为 11 的区间的价值和,即
a[ri]−a[li]=(a[ri]−a[ri−1])+(a[ri−1]−a[ri−2])+…+(a[li+1]−a[li]) a[r_i]-a[l_i]=(a[r_i]-a[r_i-1])+(a[r_i-1]-a[r_i-2])+\ldots+(a[l_i+1]-a[l_i]) a[ri​]−a[li​]=(a[ri​]−a[ri​−1])+(a[ri​−1]−a[ri​−2])+…+(a[li​+1]−a[li​])

​​  因此 问题可以简化 为 找 xxx 个长度为 111 的区间 (li,li+1](l_i,l_i+1](li​,li​+1] 使得 ∑i=1xa[li+1]−a[li]\sum_{i=1}^{x} a[l_i+1]-a[l_i]∑i=1x​a[li​+1]−a[li​] 价值最大化。

​​  贪心的角度考虑我们每次选择贡献大于 000 的区间即能使得答案最大化,因此最后答案为
ans=∑i=1n−1max⁡{0,a[i]−a[i−1]} \textit{ans}=\sum_{i=1}^{n-1}\max\{0,a[i]-a[i-1]\} ans=i=1∑n−1​max{0,a[i]−a[i−1]}

​​  其中 nnn 为数组的长度。

​​  需要说明的是,该贪心算法只能用于计算最大利润,计算的过程并不是实际的交易过程。

​​  考虑题目中的例子 [1,2,3,4,5][1,2,3,4,5][1,2,3,4,5],数组的长度 n=5n=5n=5,由于对所有的 1≤i<n1 \le i < n1≤i<n 都有 a[i]>a[i−1]a[i]>a[i-1]a[i]>a[i−1],因此答案为
ans=∑i=1n−1a[i]−a[i−1]=4 \textit{ans}=\sum_{i=1}^{n-1}a[i]-a[i-1]=4 ans=i=1∑n−1​a[i]−a[i−1]=4

​​  但是实际的交易过程并不是进行 444 次买入和 444 次卖出,而是在第 111 天买入,第 555 天卖出。

代码实现
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int ans = 0, size = prices.size();
        if(size <= 1) return 0;
        for (int i = 1; i < size; i++) {
            if (prices[i] > prices[i-1]) {  // 卖出有利可图
                ans += (prices[i] - prices[i-1]);
            }
        }
        return ans;
    }
};

Leetcode 官方题解:

class Solution {
public:
    int maxProfit(vector<int>& prices) {   
        int ans = 0;
        int n = prices.size();
        for (int i = 1; i < n; ++i) {
            ans += max(0, prices[i] - prices[i - 1]);	// 相邻两者的差为降序则+0
        }
        return ans;
    }
};
复杂度分析

时间复杂度:O(n)O(n)O(n),其中 nnn 为数组的长度。我们只需要遍历一次数组即可。
空间复杂度:O(1)O(1)O(1)。只需要常数空间存放若干变量。

方法二:动态规划

思路

​​  考虑到「不能同时参与多笔交易」,因此每天交易结束后只可能存在手里有一支股票或者没有股票的状态。

​​  定义状态 dp[i][0]\textit{dp}[i][0]dp[i][0] 表示第 iii 天交易完后手里没有股票的最大利润,dp[i][1]\textit{dp}[i][1]dp[i][1] 表示第 iii 天交易完后手里持有一支股票的最大利润(iii 从 000 开始)。

​​  考虑 dp[i][0]\textit{dp}[i][0]dp[i][0] 的转移方程,如果这一天交易完后手里没有股票,那么可能的转移状态为前一天已经没有股票,即 dp[i−1][0]\textit{dp}[i-1][0]dp[i−1][0],或者前一天结束的时候手里持有一支股票,即 dp[i−1][1]\textit{dp}[i-1][1]dp[i−1][1],这时候我们要将其卖出,并获得 prices[i]\textit{prices}[i]prices[i] 的收益。因此为了收益最大化,我们列出如下的状态转移方程:
dp[i][0]=max⁡{dp[i−1][0],dp[i−1][1]+prices[i]} \textit{dp}[i][0]=\max\{\textit{dp}[i-1][0],\textit{dp}[i-1][1]+\textit{prices}[i]\} dp[i][0]=max{dp[i−1][0],dp[i−1][1]+prices[i]}

​​  再来考虑 dp[i][1]\textit{dp}[i][1]dp[i][1],按照同样的方式考虑转移状态,那么可能的转移状态为前一天已经持有一支股票,即 dp[i−1][1]\textit{dp}[i-1][1]dp[i−1][1],或者前一天结束时还没有股票,即 dp[i−1][0]\textit{dp}[i-1][0]dp[i−1][0],这时候我们要将其买入,并减少 prices[i]\textit{prices}[i]prices[i] 的收益。可以列出如下的状态转移方程:
dp[i][1]=max⁡{dp[i−1][1],dp[i−1][0]−prices[i]} \textit{dp}[i][1]=\max\{\textit{dp}[i-1][1],\textit{dp}[i-1][0]-\textit{prices}[i]\} dp[i][1]=max{dp[i−1][1],dp[i−1][0]−prices[i]}

​​  对于初始状态,根据状态定义我们可以知道第 000 天交易结束的时候 dp[0][0]=0\textit{dp}[0][0]=0dp[0][0]=0,dp[0][1]=−prices[0]\textit{dp}[0][1]=-\textit{prices}[0]dp[0][1]=−prices[0]。

​​  因此,我们只要从前往后依次计算状态即可。由于全部交易结束后,持有股票的收益一定低于不持有股票的收益(买股票花钱,废话),因此这时候 dp[n−1][0]\textit{dp}[n-1][0]dp[n−1][0] 的收益必然是大于 dp[n−1][1]\textit{dp}[n-1][1]dp[n−1][1] 的,最后的答案即为 dp[n−1][0]\textit{dp}[n-1][0]dp[n−1][0]。

​​  注意到上面的状态转移方程中,每一天的状态只与前一天的状态有关,而与更早的状态都无关,因此我们不必存储这些无关的状态,只需要将 dp[i−1][0]\textit{dp}[i-1][0]dp[i−1][0] 和 dp[i−1][1]\textit{dp}[i-1][1]dp[i−1][1] 存放在两个变量中,通过它们计算出 dp[i][0]\textit{dp}[i][0]dp[i][0] 和 dp[i][1]\textit{dp}[i][1]dp[i][1] 并存回对应的变量,以便于第 i+1i+1i+1 天的状态转移即可。

代码实现

Leetcode 官方题解:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        int dp0 = 0, dp1 = -prices[0];
        for (int i = 1; i < n; ++i) {
            int newDp0 = max(dp0, dp1 + prices[i]);
            int newDp1 = max(dp1, dp0 - prices[i]);
            dp0 = newDp0;
            dp1 = newDp1;
        }
        return dp0;
    }
};
复杂度分析

时间复杂度:O(n)O(n)O(n),其中 nnn 为数组的长度。一共有 2n2n2n 个状态,每次状态转移的时间复杂度为 O(1)O(1)O(1),因此时间复杂度为 O(2n)=O(n)O(2n)=O(n)O(2n)=O(n)。
空间复杂度:O(n)O(n)O(n)。我们需要开辟 O(n)O(n)O(n) 空间存储动态规划中的所有状态。如果使用空间优化,空间复杂度可以优化至 O(1)O(1)O(1)。

【简单】力扣算法题解析LeetCode122:买卖股票的最佳时机 II 本文探讨了股票买卖问题,目标是通过多次买卖股票(同一时间最多持有一股)来获取最大利润。核心思路是抓住所有上升波段,将相邻两天价格上涨的差值累加即为最大利润。算法通过一次遍历数组即可完成,时间复杂度为 O(n),空间复杂度为 O(1)。Java 实现代码展示了如何高效计算总利润,适用于大规模数据输入。该方法通过分解连续上升波段为相邻日利润之和,确保不遗漏任何可能的利润片段。 阅读详情

相关推荐

STM32F0实现数字化SPWM纯正弦波逆变器

这个没啥好说的,搭电路的事。其核心思想是两边桥臂分别由两个180度相位差的正弦波与三角载波比较来控制,优点是在开关器件工作频率一样的情况下,输出PWM频率是单极性SPWM的2倍,能够明显减少谐波,因此只需要相对较小的电感和电容滤波器件就可以起到很好的滤波效果,提升了系统的性能,也精简了系统体积,降低了成本。而双极性pwm则是在整个正弦周期内,四只管子都在高频开关状态工作,对角线上的管子一起导通,另一对角线上管子互补导通,实际上只需要一路互补的PWM控制,负载上电压在正电压和负电压之间切换,不出现0v。

forlifefor的专栏 1万+

LeetCode题解第122题

LeetCode第122题: 122题.买卖股票的最佳时机 1、思路:如果第二天的售价大于当天的售价则当天买入第二天卖出,这样算的话可能出现当天卖出又买入的情况,所以不是实际的买入和卖出过程,仅仅是为了算出最大利润而采用的方法。 class Solution { public int maxProfit(int[] prices) { int count = 0; for(int i = 0; i < prices.length - 1; i++){

zhouyu的博客 782

vmware vsphere 证书过期告警处理方法

vSphere Clinet 管理页面出现“证书告警” ,检查证书未发现现有证书有过期现象

m0_51902127的博客 3635

贪心—leetcode每日一题—122.买卖股票的zuijia时机

题目: 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 思路1: 贪心:只要今天比明天小就买入,然后在第二天卖出。 解答1: class Solution: def maxProfit(self, prices: List[int]) -> int: res=0 n=len(pric

jqq125的博客 949

[华中科技计组实验]logisim完成单周期5级流水MIPS CPU

[华中科技计组实验]logisim完成单周期5级流水MIPS32 CPU hu~,终于完成了,真是费劲呐 支持24条指令,5级流水线,可以对分支指令处理,寄存器冲突处理,指令ROM为1K,数据RAM为1M,32位MIPS指令集CPU 但是… 大量使用比较器造成硬件开销巨大,测试一下发现这尼玛真是个老爷车还没单周期跑的快,自己电脑cpu占百分之八九十只能跑到20多赫兹,一个走马灯跑了半天,可优化空间太大了,写了那么多天造成这个破样,有点悲剧。。。 先放个图大伙参考就行了,要是有人想听思路的话接下来再更 .

zrc的博客 1万+

ROS2+PYTHON VENV虚拟环境配置方法

ROS2+PYTHON VENV配置方法本篇针对的是python。

下雨夏云的博客 554

买卖股票的最佳时机 II

题目 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 示例 1: 输入: [7,1,5,3,6,4] 输出: 7 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 =

qq_36314864的博客 272

国家自然基金回避专家有必要填写吗?被回避专家能看到吗?

不填也能中填1–2个最保险只填1个最直接竞争者。✅一句话结论可以不填,但建议填1–2个被回避专家绝对看不到如果你愿意,我可以再告诉你一个很多人不知道的国家自然基金“评审分组规则”——它其实决定了你的项目最可能送到哪些专家手里,这对地区基金中标率影响很大。

qq_15963745的博客 155

LeetCode122之股票买卖的最好时机(相关话题:动态规划,记忆搜索,状态机,贪心算法)

动态规划,记忆搜索,状态机,贪心算法

数据与算法架构提升之路专栏 981

【深度学习|Transformer模型学习】什么是前馈神经网络(Feed-Forward Neural Network)?将前馈神经网络中的全连接层变成1*1卷积层会有什么样的效果?

【深度学习|Transformer模型学习】什么是前馈神经网络(Feed-Forward Neural Network)?将前馈神经网络中的全连接层变成1*1卷积层会有什么样的效果?

985小水博的摸鱼日常 1374

K8S搭建(centos)完整版

每个人都有惰性,但不断学习是好好生活的根本,共勉!

感谢阅读 4141

[力扣LeetCode]122-买卖股票的最佳时机 II

[力扣LeetCode]122-买卖股票的最佳时机 II

JoeyTanHDU的博客 674

三态门Multisim电路仿真——硬件工程师笔记

三态门原理及应用摘要 三态门是具有高电平(1)、低电平(0)和高阻态(Z)三种输出的逻辑电路,通过使能端(EN)控制状态切换。高阻态时输出端等效断路,避免信号冲突。其核心应用包括: 总线系统:多设备共享总线时,仅使能选中设备的三态门,其余保持高阻态,防止干扰。 数据选择器:利用三态门切换多路输入信号,简化电路设计。 实现方式分两种: TTL三态门(三极管构成):低电平使能有效,仿真验证输出逻辑与高阻态。 MOS三态门(MOS管构成):高电平使能有效,仿真显示使能信号控制输出状态。 文中还附硬件工程师笔试面试

XU157303764的博客 2004

LeetCode第122题_买卖股票的最佳时机II

给你一个整数数组prices,其中prices[i]表示某支股票第i天的价格。在每一天,你可以决定是否购买和/或出售股票。你在任何时候只能持有股票。你也可以先购买,然后在出售。返回你能获得的利润。

qq_40263592的博客 1807

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

『力扣刷题』122_买卖股票的最佳时机II 解题代码

LeetCode-cn 力扣刷题 LeetCode-cn力扣刷题目录 122_买卖股票的最佳时机II 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 示例 1: 输入: [7,1,5,3,6,4] 输出: 7 解释...

Paradox 296

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

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

解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4。随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3。从图中可以发现,其实我们需要收集每天的正利润就可以,收集正利润的区间,就是股票买卖的区间,而我们只需要关注最终利润,不需要记录区间。这道题目可能我们只会想,选一个低的买入,再选个高的卖,再选一个低的买入…

m0_73841621的博客 1232

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

力扣122. 买卖股票的最佳时机 II

给你一个整数数组prices,其中prices[i]表示某支股票第i天的价格。在每一天,你可以决定是否购买和/或出售股票。你在任何时候只能持有股票。你也可以先购买,然后在出售。返回你能获得的利润。7在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4。随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3。

2301_79385646的博客 639

算法学习——LeetCode力扣动态规划篇6(121. 买卖股票的最佳时机、122. 买卖股票的最佳时机 II、123. 买卖股票的最佳时机 III)

算法学习——LeetCode力扣动态规划篇6(121. 买卖股票的最佳时机、122. 买卖股票的最佳时机 II、123. 买卖股票的最佳时机 III)

拉依达不拉跨的博客 1403

力扣Leetcode之Java刷题122买卖股票的最佳时机 II

leetcode之Java刷题

小李子Lee 236

Java算法-力扣leetcode-122. 买卖股票的最佳时机 II

Java算法-力扣leetcode-122. 买卖股票的最佳时机 II 给你一个整数数组prices,其中prices[i]表示某支股票第i天的价格。 在每一天,你可以决定是否购买和/或出

javaphpsqlmysql的博客 1088

LeetCode:122. 买卖股票的最佳时机 II(python)

LeetCode:122. 买卖股票的最佳时机 II(python) 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 示例 1: 输入: [7,1,5,3,6,4] 输出: 7 解释: 在第 2 天(股票价格 = 1)...

wk的博客 1658

力扣第122题:买卖股票的最佳时机 II

本题的解法采用了贪心算法,通过遍历股价数组,找出所有能够获得利润的买卖机会。每当股价上涨时,我们就进行卖出,并累积利润。最终,我们得到了最大利润。时间复杂度为OnO(n)On,空间复杂度为O1O(1)O1,是一个高效的解法。

weixin_48941116的博客 1121

LeetCode 力扣 122. 买卖股票的最佳时机 II 贪心

大家觉得写还可以,可以点赞、收藏、关注一下吧! 也可以到我的个人博客参观一下,估计近几年都会一直更新!和我做个朋友吧!https://motongxue.cn 文章目录122. 买卖股票的最佳时机 II ????题目描述注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。示例 1:示例 2:示例 3:提示:分析代码提交结果 122. 买卖股票的最佳时机 II ???? 题目描述 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你可以

motongxue的博客 304

LeetCode 122. 买卖股票的最佳时机 II(中等)

LeetCode 122. 买卖股票的最佳时机 II 题解

ZeroBugX的博客 982

力扣(leetcode)每日一题 122 买卖股票的最佳时机 II |华为od考题

每一步都进行贪心。把累加的增长更新到res中华为od题目为:商人经营一家店铺,有number种商品,由于仓库限制每件商品的最大持有数量是,每种商品的价格是通过对商品的买进和卖出获取利润,请给出商人在days天内能获取的最大的利润注:同一件商品可以反复买进和卖出。

ganjiee0007的博客 403

LeetCode 122. 买卖股票的最佳时机 II Java

LeetCode 122. 买卖股票的最佳时机 II java 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 示例 1: 输入: [7,1,5,3,6,4] 输出: 7 解释: 在第 2 天(股票价格 = 1)的时候买...

lele的专栏 456
上一篇: Leetcode(763)——划分字母区间
下一篇: Leetcode(665)——非递减数列
486L
博客等级 码龄7年 20粉丝 117原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值