贪心算法:买卖股票的最佳时机II

贪心有时候比动态规划更巧妙,更好用!

通知:一些录友基础比较薄弱,不知道从哪里开始刷题。可以看一下公众号左下角的「算法汇总」,「算法汇总」已经把题目顺序编排好了,这是全网最详细的刷题顺序了,方便录友们从头打卡学习,「算法汇总」会持续更新!

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

题目链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/

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

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

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

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

示例 2:
输入: [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。

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

提示:

  • 1 <= prices.length <= 3 * 10 ^ 4
  • 0 <= prices[i] <= 10 ^ 4

思路

本题首先要清楚两点:

  • 只有一只股票!
  • 当前只有买股票或者买股票的操作

想获得利润至少要两天为一个交易单元。

贪心算法

这道题目可能我们只会想,选一个低的买入,在选个高的卖,在选一个低的买入.....循环反复。

「如果想到其实最终利润是可以分解的,那么本题就很容易了!」

如果分解呢?

假如第0天买入,第3天卖出,那么利润为:prices[3] - prices[0]。

相当于(prices[3] - prices[2]) + (prices[2] - prices[1]) + (prices[1] - prices[0])。

「此时就是把利润分解为每天为单位的维度,而不是从0天到第3天整体去考虑!」

那么根据prices可以得到每天的利润序列:(prices[i] - prices[i - 1]).....(prices[1] - prices[0])。

如图:

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

一些同学陷入:第一天怎么就没有利润呢,第一天到底算不算的困惑中。

第一天当然没有利润,至少要第二天才会有利润,所以利润的序列比股票序列少一天!

从图中可以发现,其实我们需要收集每天的正利润就可以,「收集正利润的区间,就是股票买卖的区间,而我们只需要关注最终利润,不需要记录区间」

那么只收集正利润就是贪心所贪的地方!

「局部最优:收集每天的正利润,全局最优:求得最大利润」

局部最优可以推出全局最优,找不出反例,试一试贪心!

对应C++代码如下:

class Solution {public:    int maxProfit(vector<int>& prices) {        int result = 0;        for (int i = 1; i < prices.size(); i++) {            result += max(prices[i] - prices[i - 1], 0);        }        return result;    }};
  • 时间复杂度O(n)
  • 空间复杂度O(1)

动态规划

动态规划将在下一个系列详细讲解,本题解先给出我的C++代码(带详细注释),感兴趣的同学可以自己先学习一下。

class Solution {public:    int maxProfit(vector<int>& prices) {        // dp[i][1]第i天持有的最多现金        // dp[i][0]第i天持有股票后的最多现金        int n = prices.size();        vector<vector<int>> dp(n, vector<int>(2, 0));        dp[0][0] -= prices[0]; // 持股票        for (int i = 1; i < n; i++) {            // 第i天持股票所剩最多现金 = max(第i-1天持股票所剩现金, 第i-1天持现金-买第i天的股票)            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]);            // 第i天持有最多现金 = max(第i-1天持有的最多现金,第i-1天持有股票的最多现金+第i天卖出股票)            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i]);        }        return max(dp[n - 1][0], dp[n - 1][1]);    }};
  • 时间复杂度O(n)
  • 空间复杂度O(n)

总结

股票问题其实是一个系列的,属于动态规划的范畴,因为目前在讲解贪心系列,所以股票问题会在之后的动态规划系列中详细讲解。

「可以看出有时候,贪心往往比动态规划更巧妙,更好用,所以别小看了贪心算法」

「本题中理解利润拆分是关键点!」 不要整块的去看,而是把整体利润拆为每天的利润。

一旦想到这里了,很自然就会想到贪心了,即:只收集每天的正利润,最后稳稳的就是最大利润了。

就酱,「代码随想录」是技术公众号里的一抹清流,值得推荐给你的朋友同学们!

打算从头开始打卡的录友,可以在「算法汇总」这里找到历史文章,很多录友都在从头打卡,你并不孤单!

(0)

相关推荐

  • ​LeetCode刷题实战264:丑数 II

    算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试.所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 ! 今天和大家 ...

  • 动态规划(DP)

    本课程是从少年编程网转载的课程,目标是向中学生详细介绍计算机比赛涉及的编程语言,数据结构和算法.编程学习最好使用计算机,请登陆 www.3dian14.org (免费注册,免费学习). 本月7月13日 ...

  • Python|动态规划问题--斐波那契数列

    斐波那契数列斐波那契数列其表达式如下: 递归算法通过公式我们不难看出,其第一项和第二项为1,当x>=3时,斐波那契数列的第x项就等于其前两项的和.所以我们可以得出代码如下:public stat ...

  • ​LeetCode刷题实战188:买卖股票的最佳时机 IV

    算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试.所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 ! 今天和大家 ...

  • 【力扣】123. 买卖股票的最佳时机 III

    给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你最多可以完成 两笔 交易. 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的 ...

  • Python|买卖股票的最佳时机

    问题描述给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格.如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润.注意:你不能在买入股票前卖出股 ...

  • 老股民手把手教你如何用KDJ精准买卖股票 收藏

    首先我们先来看下什么叫:KDJ指标 KDJ指标又叫随即指标,由K线.D线和J线三条曲线所组成,是一种中短线的技术指标分析指标. KDJ指标只判断股票的超买超卖的现象,在KDJ指标中则融合了引用了平均线 ...

  • 20年老股民买卖股票不亏战法,只看这两条均线

    两条均线:5均线和8均线. 一个简单的2条均线就可以应对复杂的走势,可以在任何复杂的市场生存,无论大盘怎么走,绝对安全的操作.大盘不符合条件股都不买. 操作方法: ①确认站上5周线进入,站上8周线加仓 ...

  • 一个短线炒股高手买卖股票方法,可以收藏!

    每一个完整的波段,基本上包括8根到10根K线.其中,在上升通道(或者下降通道)中,一般有5根到7根上涨(下跌),3根振荡下跌(回升),上一个组合 运行完毕,再度进入下一个组合,两个组合之间的衔接转换K ...

  • 贪心算法简介

    贪婪算法 贪心算法(Greedy Algorithm) 简介贪心算法,又名贪婪法,是寻找最优解问题的常用方法,这种方法模式一般将求解过程分成若干个步骤,但每个步骤都应用贪心原则,选取当前状态下最好/最 ...

  • 成交量买卖股票

    这是上升趋势,量升价涨 这是下降趋势,要知道一个趋势是怎么形成的,下面来讲讲成交量买卖原则 成交量买卖原则: 1.只选取主要趋势向上,正处于上升通道的股票进行操作,决不理会重要趋势明显处于下降通道的股 ...

  • RSI指标是如何计算的?股票高手教你正确买卖股票

    RSI指标交叉信号有很好的实战作用.如何运用RSI指标交叉信号?下面我们一起来看一看! 1.死叉信号 股价经过一段时间的上涨走势后,在高位区域6日RSI线与12日RSI线形成死叉,其死叉信号也不受绝对 ...