描述
假设你有一个数组,它的第i个元素是一支给定的股票在第i天的价格。设计一个算法来找到最大的利润。你最多可以完成两笔交易。
样例
给出一个样例数组 [4,4,6,1,1,4,2,5], 返回 6
思路:
分为五个阶段,如下图所示。
股票3.png
考虑dp[n][k]为前n支股票在阶段k能获得的最大利润。
如果k为1,3,5,意味着此时并没有持有股票。那么前一状态n-1支股票只有两种取法,一种是前n-1支股票本来就在k的位置,即遍历到前n-1支股票仍然没有股票,没有利润,因此dp[n][k]=dp[n-1][k]。另一种是n-1时持有股票,即必然处于k-1的状态,到n时正好卖出,即dp[n][k]=dp[n-1][k-1]+prices[n-1]-prices[n-2]。二者取最大值。
如果k为2,4,意味此时持有股票。那么前一状态n-1支股票有三种取法。
1.前n-1支股票也处于状态k,则此时利润为dp[n][k]=dp[n-1][k]+prices[n-1]-prices[n-2]。
2.前n-1支股票处于状态k-1,没有股票,则在n-1时刻买入,此时dp[n][k]=dp[n-1][k-1]。
3.前n-1支股票处于状态k-2,即第一次持有股票,卖出去后再买入当天的股票,此时dp[n][k]=dp[n-1][k-2]+prices[n-1]-prices[n-2]。
三者取最大值。
结果返回没有持有股票时候的最大值就行了。具体实现如下。
class Solution {
public:
/**
* @param prices: Given an integer array
* @return: Maximum profit
*/
int maxProfit(vector<int> &prices) {
// write your code here
int n=prices.size();
if(!n)
{
return 0;
}
vector<vector<int>> dp(n+1,vector<int>(6,0));
dp[0][1]=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=5;j+=2)
{
dp[i][j]=dp[i-1][j];
if(j-1>0 && i>=2)
{
dp[i][j]=max(dp[i][j],dp[i-1][j-1]+prices[i-1]-prices[i-2]);
}
}
for(int j=2;j<=5;j+=2)
{
dp[i][j]=dp[i-1][j-1];
if(i>=2)
{
dp[i][j]=max(dp[i][j],dp[i-1][j]+prices[i-1]-prices[i-2]);
}
if(j-2>0 && i>=2)
{
dp[i][j]=max(dp[i][j],dp[i-1][j-2]+prices[i-1]-prices[i-2]);
}
}
}
return max(dp[n][1],max(dp[n][3],dp[n][5]));
}
};
网友评论