Leetcode 714. Best Time to Buy and Sell Stock with Transaction Fee

题目

链接:https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/

**Level: ** Medium

Discription:
Your are given an array of integers prices, for which the i-th element is the price of a given stock on day i; and a non-negative integer fee representing a transaction fee.

You may complete as many transactions as you like, but you need to pay the transaction fee for each transaction. You may not buy more than 1 share of a stock at a time (ie. you must sell the stock share before you buy again.)

Return the maximum profit you can make.

Example 1:

Input: prices = [1, 3, 2, 8, 4, 9], fee = 2
Output: 8
Explanation: The maximum profit can be achieved by:
Buying at prices[0] = 1
Selling at prices[3] = 8
Buying at prices[4] = 4
Selling at prices[5] = 9
The total profit is ((8 - 1) - 2) + ((9 - 4) - 2) = 8.

Note:

  • 0 < prices.length <= 50000.
  • 0 < prices[i] < 50000.
  • 0 <= fee < 50000.

代码一(DP)

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
        int profit=0;
        int hold[50001]={0};//持有股票
        int nohold[50001]={0};//不持有股票
        hold[0]=-prices[0];
        nohold[0]=0;
        for(int i=1;i<prices.size();i++)
        {
            nohold[i]=max(nohold[i-1],hold[i-1]+prices[i]-fee);
            hold[i]=max(hold[i-1],nohold[i-1]-prices[i]);       
        }
        return nohold[prices.size()-1];
    }
};

思考

  • 算法时间复杂度为O((n)),空间复杂度为O((n) ),这里空间复杂度其实可以优化,因为两个max函数中,如果nohold改变了即取了右边的值,hold只会取左边的值(大小关系),则每个状态其实只与前一前一天的状态有关,当天的nohold和hold并不会相互影响,所以可以只用一个变量存放nohold和hold,而不需要用数组。
  • 代码一是动态规划的思想。拆分成小问题是每一天的收益,每一天有两种情况,持有股票和不持有股票,它们的收益分别用hold和nohold来表示。
  • 当天持有股票的状态有两个可能的原因,一是昨天持有股票今天不变,二是昨天未持有,今天购入,那区分二者用一个max函数,选择收益最大的那种策略。转移方程为hold[i]=max(hold[i-1],nohold[i-1]-prices[i])。
  • 当天未持有股票的状态有两个可能的原因,一是昨天未持有股票今天不变,二是昨天持有,今天卖出,那区分二者用一个max函数,选择收益最大的那种策略。转移方程为nohold[i]=max(nohold[i-1],hold[i-1]+prices[i]-fee);。
  • 最后一天是不持有股票的,所以输出nohold的最后的值。

代码二(贪心)

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
        int sell=0;
        int buy=0;
        int profit=0;
        for(int i=0;i<prices.size();i++)
        {
            if(buy==0)
                buy=prices[i];
            else 
            {
                if(sell==0)
                {
                    if(prices[i]<buy)
                        buy=prices[i];
                    else if(prices[i]-buy>fee)
                        sell = prices[i];
                    else
                        continue;
                }
                else 
                {
                    if(prices[i]<=sell-fee)
                    {
                        profit+=sell-buy-fee;
                        sell=0;
                        buy=prices[i];
                    }
                    else if(prices[i]>sell)
                        sell=prices[i];
                    else
                        continue;
                }
            }
        }
        if(sell&&buy)
            profit+=sell-buy-fee;
        return profit;
    }
};

思考

  • 算法时间复杂度为O((n)),空间复杂度为O((1) )。
  • 代码二是贪心的思想。保证每一笔交易都是最大化收益,关键是卖出的时间点,只当价格低于sell-fee时卖出。
原文地址:https://www.cnblogs.com/zuotongbin/p/10545921.html