当前位置: 首页 > article >正文

代码随想录算法训练营Day49|121. 买卖股票的最佳时机、122.买卖股票的最佳时机II

目录

121. 买卖股票的最佳时机

方法一:暴力解法 

方法二:贪心

方法三:动态规划

算法实现

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

前言

思路

算法实现

总结:


121. 买卖股票的最佳时机

题目链接

文章链接

方法一:暴力解法 

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

         暴力解法的思路较为简单,但是提交超时了;

方法二:贪心

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int low = INT_MAX;
        int result = 0;
        for (int i = 0; i < prices.size(); i++) {
            low = min(low, prices[i]);
            // 可以保证最大值一定在最小值右侧
            result = max(result, prices[i] - low);
        }
        return result;
    }
};

        贪心的思路,股票只买卖一次,取左值最小值,取右值最大值,得到的差值为最大利润。

方法三:动态规划

        利用动规五部曲进行分析:

1.确定dp数组及其下标含义:

        dp[i][0]表示第i天持有股票所拥有的最大现金,一开始现金是0,那么加入第i天买入股票现金就是 -prices[i], 是一个负数。(此处的持有不是指当天买入,可能是前面几天买入的股票);

        dp[i][1]表示第i天不持有股票所拥有的最大现金;

2.确定递推公式:

        如果第i天持有股票即dp[i][0], 那么可以由两个可能来源

  • 第i - 1天就持有股票,没有卖出,此时dp[i][0] = dp[i - 1][0];
  • 第i - 1天没有持有股票,而是在第i天买入,此时dp[i][0] = -prices[i]

        那么dp[i] 应该选择两种情况中的最大值:dp[i][0] = max(dp[i - 1][0],  -prices[i]);

        如果第i天未持有股票即dp[i][1],同样可能有两个来源:

  • 第i - 1天就未持有股票即dp[i - 1][1]:dp[i][1] = dp[i - 1][1];
  • 第i - 1天还持有股票,在第i天卖出:dp[i][1] = dp[i - 1][0] + prices[i];

        dp[i]依然是取两种情况中的最大值:dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i]).

3.dp数组初始化:

        一开始现金是0,在第一天买入股票(持有股票)现金就是-prices[0],即dp[0][0] = -prices[0],第一天未持有股票所拥有的现金就是0,即dp[0][1] = 0;

4.确定遍历顺序:

        从递推公式可以看出dp[i]都是由dp[i - 1]推导出来的,那么一定是从前向后遍历。

5.打印dp数组:

        以示例1,输入:[7,1,5,3,6,4]为例,dp数组状态如下:

        

        dp[5][1]就是最终结果,因为同一天不持有股票时的钱一定比持有股票时的钱多。

算法实现
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int len = prices.size();
        vector<vector<int>> dp(len, vector<int>(2));
        dp[0][0] -= prices[0];
        dp[0][1] = 0;
        for (int i = 1; i < len; i++) {
            dp[i][0] = max(dp[i - 1][0], -prices[i]);
            dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);
        }
        return dp[len - 1][1];
    }
};

        从递推公式可以看出,dp[i]只是依赖于dp[i - 1]的状态,可以对以上算法进行优化,使用滚动数组来节省空间。

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

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

题目链接

文章链接

前言

         前一题买卖股票问题只能买卖一次股票,而本题没有一次的限制,虽然每次最多只能仍然只能持有一张股票,但是可以多次买入卖出股票。

思路

        本题与上一题的不同主要在于推导dp[i][0]时,如果第i天持有股票,第一种情况同样是第i - 1天就持有了股票,dp[i][0] = dp[i - 1][0];而第二种情况则是第i - 1天没有持有股票,在第i天购入股票,此时不再是0 - prices[i],因为当前的现金不一定是0,前面可能已经经过了好几次的股票买入和卖出操作,因此此时的dp[i][0] = dp[i - 1][1] + prices[i];

        未持有股票的情况dp[i][1]与上题相同,依然是dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i])。

算法实现

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

        同样也可以利用滚动数组进行优化,代码如下:

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

总结:

        今天学了买卖股票类的问题,初步简单掌握。


http://www.kler.cn/a/228804.html

相关文章:

  • 日志收集Day002
  • 安全测评主要标准
  • 正态分布检验(JB检验和威尔克检验)和斯皮尔曼相关系数(继上回)
  • 53,【3】BUUCTF WEB october 2019 Twice SQLinjection
  • 力扣动态规划-2【算法学习day.96】
  • 《AI赋能光追:开启图形渲染新时代》
  • 【IMAX6U移植OpenCV】
  • 15.1 项目实践_OA系统
  • 【RT-DETR有效改进】UNetv2提出的一种SDI多层次特征融合模块(细节高效涨点)
  • 浅谈QT的几种线程的使用和区别。
  • 如何部署Linux AMH服务器管理面板并结合内网穿透远程访问
  • 【AI数字人-论文】Geneface论文
  • H5调用安卓原生相机API案例
  • Java学习day29:线程池Pool中创建线程方式(面试必考!)
  • 《热辣滚烫》预售狂潮来袭,贾玲、马丽、杨紫三大女神联袂出演。
  • (4)【Python数据分析进阶】Machine-Learning模型与算法应用-回归、分类模型汇总
  • Java实现线程安全的几种方式:常量/数据私有/互斥同步/非阻塞同步
  • 【数据结构 10】位图
  • jmeter-问题一:关于线程组,线程数,用户数详解
  • 5分钟快速掌握 XML (Extensible Markup Language)
  • 【51单片机】开发板&开发软件(Keil5&STC-ISP)简介&下载安装破译传送门(1)
  • QT styleSheet——控件设置样式表
  • 【BBF系列协议】TR101 基于以太网的宽带聚合的迁移
  • 交友系统---让陌生人变成熟悉人的过程。APP小程序H5三端源码交付,支持二开。
  • Hudi学习 6:Hudi使用
  • 如何在Vue应用程序中使用Vue-Router来实现路由嵌套动画效果