zoukankan      html  css  js  c++  java
  • Leetcode炒股问题

    Leetcode上一共出现了6道炒股问题:一个数组代表一支股票每天的价格,买了股票再卖出算一次交易,多个交易不能交叉,即只能卖了股票之后才能再买。求最大收益。

    Leetcode上有一篇post介绍了一种通用的针对这类问题的解法,值得参考。

    以下是我总结的每个问题比较容易理解的方法。

    1.Best Time to Buy and Sell Stock 交易至多一次

    这道题可以转化为求最大子数列问题。例如$[1, 7, 4, 11]$,可以转换为$[0, 6, -3, 7]$,然后计算该数组的最大子数列和即可,如果为负,返回0。

    int maxProfit(vector<int>& prices) {
            int maxCur = 0, maxSoFar = 0;
            for(int i = 1; i < prices.size(); ++i){
                maxCur = max(0, maxCur + prices[i] - prices[i - 1]);
                maxSoFar = max(maxSoFar, maxCur);
            }
            return maxSoFar;
        }

    2.Best Time to Buy and Sell Stock II 交易任意多次

    遍历数组,只要$prices[i] > prices[i-1]$,$maxprofit += prices[i] - prices[i -1]$

    int maxProfit(vector<int>& prices) {
            int maxprofit = 0;
            for(int i = 1; i < prices.size(); ++i){
                if(prices[i] > prices[i - 1])
                    maxprofit += prices[i] - prices[i - 1];
            }
            return maxprofit;
        }

    3.Best Time to Buy and Sell Stock III 至多交易两次

    分析见4

    int maxProfit(vector<int>& prices) {
            int n = prices.size();
            if(n <= 1) return 0;
            vector<vector<int>> dp(3, vector<int>(n, 0));
            for(int i = 1; i <= 2; ++i){
                int tmpMax = dp[i - 1][0] - prices[0];
                for(int j = 1; j < n; ++j){
                    dp[i][j] = max(dp[i][j - 1], prices[j] + tmpMax);
                    tmpMax = max(tmpMax, dp[i - 1][j] - prices[j]);
                }
            }
            return dp[2][n - 1];
        }

    4.Best Time to Buy and Sell Stock IV 至多交易k次

    int maxProfit(int k, vector<int>& prices) {
            int n = prices.size();
            if(n < 2) return 0;
            //如果 k >= n/2,则问题转化为可以交易任意多次,用II的方法来防止TLE
            if(k >= n / 2){
                int maxPro = 0;
                for(int i = 1; i < prices.size(); ++i){
                    if(prices[i] > prices[i - 1])
                        maxPro += prices[i] - prices[i - 1];
                }
                return maxPro;
            }
            //dp[i][j]represents the max profit up until prices[j] (Note: NOT ending with prices[j]) using at most i transactions.
            //dp[i][j] = max(dp[i][j-1], prices[j] - prices[m] + dp[i-1][m]) {m in range of [0, j-1]}
            //         = max(dp[i][j-1], prices[j] + max(dp[i-1][m] - prices[m]))
            //dp[0][j] = 0; 0 times transation makes 0 profit
            //dp[i][0] = 0; if there is only one price data point you can't make any money no matter how many times you can trade
            vector<vector<int>> dp(k + 1, vector<int>(n, 0));
            for(int i = 1; i <= k; ++i){
                int tmpMax = dp[i - 1][0] - prices[0];
                for(int j = 1; j < n; ++j){
                    dp[i][j] = max(dp[i][j - 1], prices[j] + tmpMax);
                    tmpMax = max(tmpMax, dp[i - 1][j] - prices[j]);
                }
            }
            return dp[k][n - 1];
        }

    5.Best Time to Buy and Sell Stock with Cooldown 卖了票之后第二天不能买入(cooldown 1 day)

     根据所能采取的动作,共有三种状态:$s0, s1, s2$, 在每个状态的第i天的收益为:

    s0[i] = max(s0[i - 1], s2[i - 1]); // Stay at s0, or rest from s2
    s1[i] = max(s1[i - 1], s0[i - 1] - prices[i]); // Stay at s1, or buy from s0
    s2[i] = s1[i - 1] + prices[i]; // Only one way from s1

    初始状态:

    s0[0] = 0; // At the start, you don't have any stock if you just rest
    s1[0] = -prices[0]; // After buy, you should have -prices[0] profit. Be positive!
    s2[0] = INT_MIN; // Lower base case

    Code:

    int maxProfit(vector<int>& prices) {
            int n = prices.size();
            if(n < 2) return 0;
            vector<int> s0(n);
            vector<int> s1(n);
            vector<int> s2(n);
            s0[0] = 0;
            s1[0] = -prices[0];
            s2[0] = INT_MIN;
            for(int i = 1; i < n; ++i){
                s0[i] = max(s0[i - 1], s2[i - 1]);
                s1[i] = max(s1[i - 1], s0[i - 1] - prices[i]);
                s2[i] = s1[i - 1] + prices[i];
            }
            return max(s0[n - 1], s2[n - 1]);
        }

    6.Best Time to Buy and Sell Stock with Transaction Fee 可以交易任意多次,但每次交易都会有交易费用fee

    $cash$表示第$i$天手中没有股票的最大收益

    $hold$表示第$i$天手中有股票的最大收益

    则在第$i+1$天,可以

    卖出手中的股票:$cash = max(cash, hold + prices[i] -fee)$

    或者买入股票:$hold = max(hold, cash - prices[i])$

    最后cash就是最大收益。

    We can transform $cash$ first without using temporary variables because selling and buying on the same day can't be better than just continuing to hold the stock.

    int maxProfit(vector<int>& prices, int fee) {
            int cash = 0, hold = -prices[0];
            for(int i = 1; i < prices.size(); ++i){
                cash = max(cash, hold + prices[i] - fee);
                hold = max(hold, cash - prices[i]);
            }
            return cash;
        }
  • 相关阅读:
    How the Data stored in computer?
    WinForm Vs WPF, COM/COM+ Vs .Net Assembly, COM/COM+ in ASP.Net, ... ...
    [Wonderful Explanation] ContextBound Objects and Remoting
    command
    compile the source code for specific device
    compile Android cm10.1
    Android Lint erroneously thinks min SDK version is 1
    wine Program File
    adb push framework.jar /system/framework
    Degrade ADT in Eclipse
  • 原文地址:https://www.cnblogs.com/betaa/p/11589137.html
Copyright © 2011-2022 走看看