zoukankan      html  css  js  c++  java
  • LeetCode121. 买卖股票的最佳时机

    由于只能交易一次,即买入卖出一次,所以我们考虑在某个价值较低的某天买入,在之后的某个价值较高的一天卖出,以获取最高的差价利润。

    最简单的想法是枚举所有天数,然后枚举某天之后的所有天数,更新能够获取到的最高利润。
    这样做需要两重循环,时间复杂度是O(n^2),超时。

    我们可以边枚举天数边记录当前的最低价格和能获取到的最高利润(最高利润就是当前的价格减去当前记录的最低价格)。
    这样时间复杂度可以降到O(n)。

    代码如下:

    class Solution {
    public:
        int maxProfit(vector<int>& prices) {
            int res = 0;
            int lowestPrice = INT_MAX;                  //记录截止到当前天数的最低价格
            for(auto price : prices) {
                lowestPrice = min(lowestPrice, price);            //更新最低价格
                res = max(res, price - lowestPrice);              //计算当前价格减去最低价格,更新利润(最高差价)
            }
            return res;
        }
    };
    

    这题还有一个通用的做法,可以参考买卖股票的最佳时机 IV

    用一个状态转移方程dp[i][k][0 or 1]表示当前天数第i天,最高交易次数(买入次数)为k,持有或不持有(1表示持有,0表示不持有股票时)的最高利润。

    由于这道题k最大为1,所以k只能是0或1,当k为0时dp值肯定为0,因为不买入股票就没有利润,所以状态可以压缩到二维, dp[i][0 or 1]表示第i天,持有或持有股票时的最高利润。
    具体分析可以看上面那个链接。

    代码如下:

    class Solution {
    public:
        int maxProfit(vector<int>& prices) {
            int n = prices.size();
            if(n == 0) {
                return 0;
            }
            vector<vector<int>> dp(n, vector<int>(2));
            for(int i = 0; i < n; ++i) {
                if(i == 0) {                        //边界情况要特殊处理
                    dp[i][0] = 0;
                    dp[i][1] = -prices[i];            //第0天花了prices[0]的成本买入股票
                    continue;
                }
                dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]);      //状态转移方程,不持有股票的状态由前一天也不持有股票和前一天持有股票,第i天卖掉两种状态转移而来
                dp[i][1] = max(dp[i - 1][1], -prices[i]);              //状态转移方程,持有股票的状态由前一天就持有股票和前一天不持有股票,第i天买入股票两种状态转移而来。 由于交易次数最大为1,所以前一天不持有股票,dp[i - 1][0]肯定是0,所以第二个参数是-prices[i]
            }
            return dp[n - 1][0];            //最后答案就是最后一天,不持有股票的最高利润。是dp[n - 1][0]不是dp[n - 1][1],是因为不持有股票(卖出股票)肯定比持有股票的利润高,因为买股票要钱(成本),持有股票本身没法赚钱,卖了才有利润
        }
    };
    
  • 相关阅读:
    POJ 1611 The Suspects
    POJ 2001 Shortest Prefixes(字典树)
    HDU 1251 统计难题(字典树 裸题 链表做法)
    G++ C++之区别
    PAT 乙级 1013. 数素数 (20)
    PAT 乙级 1012. 数字分类 (20)
    PAT 乙级 1009. 说反话 (20)
    PAT 乙级 1008. 数组元素循环右移问题 (20)
    HDU 6063 17多校3 RXD and math(暴力打表题)
    HDU 6066 17多校3 RXD's date(超水题)
  • 原文地址:https://www.cnblogs.com/linrj/p/13457252.html
Copyright © 2011-2022 走看看