最直观的想法就是划分成两个子问题,每个子问题变成了:求在某个范围内交易一次的最大利润
在只能交易一次的情况下,如何求一段时间内的最大利润?其实就是找股价最低的一天买进,然后在股价最高的一天卖出,当然,卖股票要在买股票之后。
用迭代法求这个问题非常容易,令profits[i]表示截至到第i天的最大利润,则profits[i+1] = max{profits[i], prices[i+1] - minPrice},其中,minPrice = min{prices[k]},0 <= k < n。但是从profits[i]没法直接得到profits[i-1]
倒过来迭代也完全没问题,令profits[i]表示从第i天开始到结束的最大利润,则profits[i] = max{profits[i+1], maxPrice - prices[i]},其中maxPrice = max{prices[k]},i+1 <= k < n。但是从profits[i]没法直接得到profits[i+1]
之后,依次枚举分割点,求解两个子问题的和即可。
代码:
1 int maxProfit(vector<int> &prices) { 2 int n = prices.size(); 3 vector<int> profits(prices.size(), 0); 4 int result = 0; 5 int tmp; 6 7 if (n < 2) 8 return 0; 9 10 tmp = 0; 11 int minPrice = prices[0]; 12 for (int i = 1; i < n; i++) { 13 tmp = max(tmp, prices[i] - minPrice); 14 profits[i] = tmp; 15 minPrice = min(minPrice, prices[i]); 16 } 17 18 tmp = 0; 19 int maxPrice = prices[n - 1]; 20 for (int i = n - 2; i >= 0; i--) { 21 tmp = max(tmp, maxPrice - prices[i]); 22 result = max(result, i > 0 ? tmp + profits[i - 1] : tmp); 23 maxPrice = max(maxPrice, prices[i]); 24 } 25 26 return result; 27 }