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.
法1:DP。O(n^2) - TLE
遍历,每个点都看一看这次不动作,或者最后一次买卖是之前第m天到今天,这几种情况哪种收益最好。
递推公式:dp[i] = Math.max(dp[i], dp[m] + prices[i - 1] - prices[m - 1] - fee); 对所有[1, i) 的m循环
法2:DP。O(n)
通过转化memo记录内容的形式,让卖股票的时候不需要care这只股票是哪一天买入的,从而避免了前面的m循环,去遍历前面是哪一天买入的导致的O(n^2)。
定义:hold[i], sold[i] 表示第I天手上有股票和没股票分别能最多揣着多少钱。(注意不是profit的感觉,而是手头现金的感觉)最后返回sold[last]
初始化:hold[0] = -prices[0]; 注意第一天如果拿着股票的话你要先垫付。
递推公式:hold[i] = max(hold[i - 1], sold[i - 1] - prices[i]); sold[i] = Math.max(sold[i - 1], hold[i - 1] + prices[i] - fee);
解释:今天的情况由昨天的决定。比如今天手上有股票,可以由昨天有股票转化而来,或者由昨天没股票转化而来。今天手上没股票同理。
法1实现 O(n^2) TLE:
class Solution { public int maxProfit(int[] prices, int fee) { if (prices == null || prices.length == 0) { return 0; } int[] dp = new int[prices.length + 1]; for (int i = 2; i < dp.length; i++) { for (int m = 1; m < i; m++) { dp[i] = Math.max(dp[i], dp[m] + prices[i - 1] - prices[m - 1] - fee); } } return dp[dp.length - 1]; } }
法2实现 O(n):
class Solution { public int maxProfit(int[] prices, int fee) { if (prices == null || prices.length == 0) { return 0; } int[] hold = new int[prices.length]; int[] sold = new int[prices.length]; hold[0] = -prices[0]; for (int i = 1; i < prices.length; i++) { hold[i] = Math.max(hold[i - 1], sold[i - 1] - prices[i]); sold[i] = Math.max(sold[i - 1], hold[i - 1] + prices[i] - fee); } return sold[sold.length - 1]; } }