714.买卖股票的最佳时机含手续费

给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 ;非负整数 fee 代表了交易股票的手续费用。

你可以无限次地完成交易,但是你每次交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。

返回获得利润的最大值。

示例 1:

输入: prices = [1, 3, 2, 8, 4, 9], fee = 2
输出: 8
解释: 能够达到的最大利润: 在此处买入 prices[0] = 1
在此处卖出 prices[3] = 8
在此处买入 prices[4] = 4
在此处卖出 prices[5] = 9
总利润: ((8 - 1) - 2) + ((9 - 4) - 2) = 8.
注意:

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

解决这个问题的关键是要知道什么时候该卖出,利润就等于卖出时价格减去之前遍历到的最小值再减去手续费,利润很好计算。

那么怎么判断是该持有还是该卖出呢?

首先从第二个数开始遍历,如果它比第一个数小,那我们就不买第一天的,买第二天的股票(这个时候更新最小值min)。

再来继续遍历,如果第三天的价格比第二天的高呢?(这个时候更新最大值max)这个时候卖不卖?无论卖或者不卖都让人为难,因为你不知道后面价格是不是会更高。所以我们是否卖出股票应该由接下来的一天决定。

所以我们看第四天的,如果第四天比第三天还高,那我们就继续观望(继续更新max)。

第五天终于跌了,跌多少的时候卖出呢?假设之前的最小值为a,第四天(也就是跌之间的最大值)的价格为b,跌了之后价格为c,第二次卖出时价格为d。那么不卖出,也就是从a-d只交易一次利润为p1 = (d-a-fee),卖出,也就是交易两次利润为p2 =(b-a+d-c-2*fee),当交易两次利润比一次利润大时,我们在下跌的时候就应该卖出,p2-p1 = b-c-fee>0,也就是b-c>fee。所以当跌了的价格超过手续费时我们就应该卖出,这样就能进行多次交易获得更大的利润。

当遍历到末尾时,只要利润大于0就应该卖出。

class Solution {
    public int maxProfit(int[] prices, int fee) {
    	int res = 0;
    	int min = prices[0];
    	int max = prices[0];
    	int cur = 0;
    	//min记录遍历到的最小值,max记录遍历到的最大值
    	//这个最难在于求什么时候卖出,取最小值为购买点,最大值减最小值即为利润
    	for(int i = 1; i < prices.length; i++) {
    		min = Math.min(min, prices[i]);
    		max = Math.max(max, prices[i]);
    		cur = Math.max(cur, prices[i] - min - fee);
            //由上述公式推导得,当下跌超过手续费时,就应该卖出
    		if(max - prices[i] > fee) {
    			res += cur;
    			cur = 0;
    			min = prices[i];
    			max = prices[i];
    		}
    	}
    	res += cur;
    	return res;
    }
}
posted @ 2020-04-09 14:22  风语如歌j  阅读(155)  评论(0编辑  收藏  举报