IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> LeetCode121&122.买卖股票的最佳时期 -> 正文阅读

[数据结构与算法]LeetCode121&122.买卖股票的最佳时期

前言

今天记录一下 「LeetCode121.买卖股票的最佳时期」和「LeetCode122.买卖股票的最佳时期Ⅱ」 两个问题的解法。先理解如何利用贪心算法解决第二题,再去想第一题,立马就能类比得到解决问题的思路,将其转化为最大连续子列和问题,并利用在线处理算法得到结果。

问题描述1

这是 「LeetCode122.买卖股票的最佳时期Ⅱ」

给定一个数组 prices ,其中 prices[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

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

贪心算法解决

如下图所示的一个股票曲线图,可以直观地看到,只需要找到 「股票开始上涨的最小值」和「股票上涨到的最大值」 ,在最小值点买入股票并在最大值点卖出股票,计算这一段之间的差,就是折线递增区间的增量,也就是这段时间内股票的最大利润。最后只需要把所有上涨时间段内的利润累加起来就是要求的结果。
1
贪心算法就是指,在对问题求解的时候,总是做出当前来看是最好的选择,某种意义上就是局部最优解。

在这道题目中,只要是在上升的,我们就计算上升的增量,然后对所有增量进行累加,并不需要找到这段完整增量区间的最小值和最大值再来求差值。

我们结合图片来理解一下,当连续几天股价都在增长的情况下,可以看成在上升的第二个点,我先卖出再买入。连续下降的时候我就不买入,这一天我手中是没有股票的。

2
也可以结合数学公式来理解,在一段上升区间 a<b<c,则这段区间的增量是 (c-a),同样可以这样计算 (b-a)+(c-b),到这一步应该一切都明明白白了。

我们只要把 prices 数组遍历一遍,并且在遍历的过程中用后一项减前一项,如果是正数则累加,负数则不加,得到 4+3=7
3
这个时候代码就呼之欲出了:

class Solution{
    public:
    int maxProfit(vector<int>&prices){
        int total = 0;
        for(int i=0;i<prices.size()-1;i++){
            total += max(prices[i+1]-prices[i],0);
        }
        return total;
    }
};

问题描述2

这是 「LeetCode121.买卖股票的最佳时期」

给定一个数组 prices ,它的第 i 个元素 prices[i]表示一支给定股票第 i 天的价格。
你只能选择某一天买入这只股票,并选择在未来的某一个不同的日子卖出该股票。
设计一个算法来计算你所能获取的最大利润。返回你可以从这笔交易中获取的最大利润。
如果你不能获取任何利润,返回 0

示例1

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

示例2

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

转化为最大连续子列和问题

这道题是让求完成一笔交易所获得的最大利润,并且在有交易完成的情况下,只能买入一次和卖出一次,有了上一题的经验,很容易将这个问题转化为「最大连续子列和」 的问题。

如下图展示的股票曲线图,上一题是避免了所有股票下跌的情况,只要上升我的利润就增加。而这道题我只能在某个区间的起点买入,在终点卖出,这个区间中股价有涨有跌,但总体上来说我是获利的,否则我一开始就不会买入。
4
通过观察可以发现,在这个区间的最小值点买入,在最大值点卖出,中间即便股价下跌也不会跌出最小值,即便有涨也不会超出最大值。

那么我们要怎么找出使得利润最大的这个区间呢?回顾上一题,我们用数组的后一个值减前一个值,并且将差为正的数累加,得到利润。而这一题,得到所有的差值之后,要使某个子区间内的差都累加起来(无论正负)的值达到最大,那么求 [7,1,5,3,6,4] 中最大利润的问题就转化为了求 [-6,4,-2,3,-2] 中最大连续子列和的问题。
5

在线处理算法解决

如果我们使用for循环把所有子列和情况都算出来再求出最大值的话,那显然时间复杂度太大了。所以这里采用「在线处理算法」,即使数据一个一个读入,返回的最大连续子列和也是当前正确的,算法时间复杂度为O(n)

对于待求数组 [-6,4,-2,3,-2] ,我们将每一项向右累加,发现更大的和则更新当前结果,如果当前子列和为负,它一定会使后面的数字变得更小,干脆抛弃,将当前子列和置为0,最后得到的结果即为最大连续子列和。

只要一次遍历,将数组 prices 的后一项减去前一项,得到的值进入「在线处理算法」,相当于数据一个一个读入,得到最大连续子列和,即最大利润。思路有了,代码同样是呼之欲出:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int len = prices.size();
        int maxSum = 0;   //最大利润
        int thisSum = 0;  //当前子列和
        for(int i=1;i<len;++i){
            thisSum += prices[i]-prices[i-1];
            if(thisSum>maxSum)
                maxSum = thisSum;  //发现更大的和则更新当前结果
            else if(thisSum<0)
                thisSum = 0; //如果当前子列和为负.它一定会使后面的数变得更小,干脆抛弃,置和为0
        }
        return maxSum;
    }
};

微信公众号文章

LeetCode121&122.买卖股票的最佳时期

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-09-03 12:10:17  更:2021-09-03 12:11:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 1:53:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码