123. Best Time to Buy and Sell Stock III***

Posted 珍妮的选择

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了123. Best Time to Buy and Sell Stock III***相关的知识,希望对你有一定的参考价值。


123. Best Time to Buy and Sell Stock III***

​https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/​

题目描述

Say you have an array for which the ​​ith​​​ element is the price of a given stock on day ​​i​​.

Design an algorithm to find the maximum profit. You may complete at most two transactions.

Note: You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again).

Example 1:

Input: [3,3,5,0,0,3,1,4]
Output: 6
Explanation: Buy on day 4 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.
Then buy on day 7 (price = 1) and sell on day 8 (price = 4), profit = 4-1 =

Example 2:

Input: [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 =

Example 3:

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit =

解题思路

强烈推荐 ​​Most consistent ways of dealing with the series of stock problems​​, 文章实在精彩啊, 将有关 Stock 的题总结了一遍, 探索了这些题之间的一致性.

C++ 实现 1

需要注意到的是, 一个隐含的影响 max profit 的因素是我们手中所拥有的股票数量. 因为在每一天我们所能采取的行动只有三种: sell, buy 以及 rest. 然而, 要完成 ​​sell​​​ 这个过程, 必须手上拥有一份股票; 而要完成 ​​buy​​​ 这个过程, 则必须保证手上没有任何股票. 因此, 倘若设置 ​​T[i][k]​​​ 表示在进行最多 ​​k​​​ 次交易的情况下在第 ​​i​​​ 天所能获得最大收益, 那么它其实可以分成两个部分: ​​T[i][k][0]​​​ 以及 ​​T[i][k][1]​​​, 前者表示采取某种行动之后手上股票变成 0 份所在第 ​​i​​​ 天所能获得的最大收益, 而后者表示采取某种行动之后手上股票变成 1 份在第 ​​i​​ 天所能获得的最大收益. 递推关系能写成:

Base cases:
T[-1][k][0] = 0, T[-1][k][1] = -Infinity
T[i][0][0] = 0, T[i][0][1] = -Infinity

Recurrence relations:
T[i][k][0] = max(T[i-1][k][0], T[i-1][k][1] + prices[i]) # sell
T[i][k][1] = max(T[i-1][k][1], T[i-1][k-1][0] - prices[i]) # buy

为了找到最大的收益, 我们只需要遍历 ​​prices​​​, 并不断更新 ​​T[i][k][0]​​​ 以及 ​​T[i][k][1]​​​, 而最后一天的最大收益就是 ​​T[i][k][0]​​, 手上是没有股票才能获得最大收益.

上面是通用的公式, 而题目中要求 ​​K = 2​​, 此时, 递推公式变为:

T[i][2][0] = max(T[i-1][2][0], T[i-1][2][1] + prices[i])
T[i][2][1] = max(T[i-1][2][1], T[i-1][1][0] - prices[i])
T[i][1][0] = max(T[i-1][1][0], T[i-1][1][1] + prices[i])
T[i][1][1] = max(T[i-1][1][1], -prices[i])

实现代码如下:

class Solution 
public:
int maxProfit(vector<int>& prices)
vector<int> T1(prices.size() + 1);
T1[0] = 0;
int s0 = 0, s1 = INT32_MIN;
for (int i = 0; i < prices.size(); ++ i)
s0 = std::max(s0, s1 + prices[i]);
s1 = std::max(s1, -prices[i]);
T1[i + 1] = s0;

s0 = 0, s1 = INT32_MIN;
for (int i = 0; i < prices.size(); ++ i)
s0 = std::max(s0, s1 + prices[i]);
s1 = std::max(s1, T1[i] - prices[i]);

return s0;

;

作者的实现更贴近公式:

public int maxProfit(int[] prices) 
int T_i10 = 0, T_i11 = Integer.MIN_VALUE;
int T_i20 = 0, T_i21 = Integer.MIN_VALUE;

for (int price : prices)
T_i20 = Math.max(T_i20, T_i21 + price);
T_i21 = Math.max(T_i21, T_i10 - price);
T_i10 = Math.max(T_i10, T_i11 + price);
T_i11 = Math.max(T_i11, -price);


return T_i20;

C++ 实现 2

用数组 ​​T​​​ 来保存每个 ​​k - 1​​​ 的状态. 这个方便扩展到 K 为其他值的情况. 可能需要对 ​​T​​ 进行优化.

class Solution 
public:
int maxProfit(vector<int>& prices)
int K = 2;
// 实际上, 不论 K 为多大, T 设置为 (2, prices.size() + 1) 的大小就行了
// 但这里为了理解方便, 就设置为 (K + 1, prices.size() + 1) 便于推广到 K != 2 的情况.
vector<vector<int>> T(K + 1, vector<int>(prices.size() + 1, 0));
int s0 = 0, s1 = INT32_MIN;
for (int k = 0; k < K; ++ k)
s0 = 0, s1 = INT32_MIN;
for (int i = 0; i < prices.size(); ++ i)
s0 = std::max(s0, s1 + prices[i]); // sell
s1 = std::max(s1, T[k][i] - prices[i]); // buy
T[k + 1][i + 1] = s0;


return s0;

;


以上是关于123. Best Time to Buy and Sell Stock III***的主要内容,如果未能解决你的问题,请参考以下文章

123. Best Time to Buy and Sell Stock III

123. Best Time to Buy and Sell Stock III

123. Best Time to Buy and Sell Stock III

123. Best Time to Buy and Sell Stock III ~~

leetcode-123. Best Time to Buy and Sell Stock III

[leetcode-123-Best Time to Buy and Sell Stock III]