zoukankan      html  css  js  c++  java
  • [LeetCode] #123 Best Time to Buy and Sell Stock III

    LeetCode 题目,原题链接 https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/。

    问题描述:一定时间区间内一只股票,最多交易两次,两次交易无重叠区域,求最大收益。

    参考:https://discuss.leetcode.com/topic/32288/2ms-java-dp-solution

    Canonical Solution

    这个问题是DP问题,因为存在两次交易,需要保存第一次交易的信息,给第二次交易做参考。

    这个问题是在第 N 天或第 N 天之前完成第二次交易的卖出,获得的收益。

    子问题是,在 N 天完成第二次交易的卖出,在第 N 天之前完成第二次交易的卖出,这两个获得的收益的最大值。再讲第二种情况进行分解,就可以分解成给 N 天时间,计算在第 2, 3, ,4, ,5, ..., N - 1 天 完成第二次交易的卖出获得的收益,这些收益中的最大值。(注:从第2天开始计算是因为有第一次交易存在,第一次交易在第0天买入,在第1天卖出,第二次交易最快只能在第2天卖出。)

    使用一个一维数组 profit1 用于记录第一次交易的收益,profit[i] 表示在第 i 天完成第一次交易的卖出,获得的第一次交易的收益。

    使用一个二维数组 porift 用于记录第二次交易的收益,profit[i][j] 表示在第 i 天完成第一次交易的卖出,第 j 天完成第二次交易的卖出(也可以不做第二次交易),获得的最大收益。

    实际使用中二维数组可以省去,因为是线性单方向遍历,不需要回溯以前的记录。

    class Solution {
    public:
        int maxProfit(vector<int>& prices) {
            int N = prices.size();
            vector<int> profit1(N, 0); // profit[i] 在第i天卖出第一支股票的收益
            for (int i = 0; i < N; ++i) {
                for (int j = i - 1; j >= 0; --j) {
                    if (prices[i] - prices[j] > profit1[i]) {
                        profit1[i] = prices[i] - prices[j];
                    }
                }
            }
            // 依据 profit1 计算 profit,profit[i][j] 在第 i 天卖出第一支股票,第 j 天卖出第二支股票
            int maxProfit = 0;
            for (int i = 0; i < N; ++i) {
                for (int j = i + 1; j < N; ++j) {
                    int profitij = 0;
                    for (int k = i; k < j; ++k) {
                        if (prices[j] - prices[k] > profitij) {
                            profitij = prices[j] - prices[k];
                        }
                    }
                    profitij += profit1[i];
                    if (profitij > maxProfit) {
                        maxProfit = profitij;
                    }
                }
            }
            return maxProfit;
        }
    };
    

    然而,这种方法Time Limit Exceeded

    聪明人的方法

    参考:https://discuss.leetcode.com/topic/32288/2ms-java-dp-solution

    在评论区有一个人,Bef0rewind,对代码进行了解释。

    public int maxProfit(int[] prices) {
        // these four variables represent your profit after executing corresponding transaction
        // in the beginning, your profit is 0. 
        // when you buy a stock ,the profit will be deducted of the price of stock.
        int firstBuy = Integer.MIN_VALUE, firstSell = 0;
        int secondBuy = Integer.MIN_VALUE, secondSell = 0;
    
        
        // (-firstBuy) is min value beteen [0, curPrice.index], firstBuy itself is a negative value
        
        // (firstSell) is max profit between [0, current.index], before update it is max profit between [0, current.index-1], after update is max(firstSell.before, curPrice + firstBuy(e.g. - minValue[0, curPrice.index]))
        
        // (secondBuy) is max profit between [0,curPrice.index] under seen prices if you hold/buy a stock between[0, curPrice.index] and haven't sell it yet.
        
        // (secondSell) is max profit between [0,curPrice.index] under seen prices if you buy a second stock between [0,curPrice.index];
        
        for (int curPrice : prices) {
            if (firstBuy < -curPrice) firstBuy = -curPrice; // the max profit after you buy first stock
            if (firstSell < firstBuy + curPrice) firstSell = firstBuy + curPrice; // the max profit after you sell it
            if (secondBuy < firstSell - curPrice) secondBuy = firstSell - curPrice; // the max profit after you buy the second stock
            if (secondSell < secondBuy + curPrice) secondSell = secondBuy + curPrice; // the max profit after you sell the second stock
        }
        
        return secondSell; // secondSell will be the max profit after passing the prices
    }
    

    这是一个空手套白狼的故事,无本生意,先借钱,买股票,用卖出去的钱偿还买股票的借款。

    遍历的时候考虑四种状态:firstBuy第一次购买股票后口袋中的钱,firstSell第一次售出股票后口袋中的钱, secondBuy第二次购买股票后口袋中的钱,secondSell第二次售出股票后口袋中的钱。

  • 相关阅读:
    最小的K个数
    CentOS 7 连接不到网络解决方法
    数组中超过一半的数字
    字符串的排列
    二叉搜索树与双向链表
    复杂链表的复制
    二叉树中和为某一数值的路径
    二叉搜索树的后序遍历序列
    从上到下打印二叉树
    java的图形文档
  • 原文地址:https://www.cnblogs.com/JingeTU/p/7542438.html
Copyright © 2011-2022 走看看