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***的主要内容,如果未能解决你的问题,请参考以下文章