目录
简介
leetcode上面有几个关于买卖股票的动态规划题。下面我们来看这种问题的模型:
给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。
注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。这里说的K笔交易是一次买入和一次卖出!!!
分析
我们可以用三维DP去记录解决这个问题。
dp[i][k][0] = max( dp[i-1][k][0], dp[i-1][k][1] + a[i] )//卖出的时候,次数不变
dp[i][k][1] = max( dp[i-1][k][1], dp[i-1][k-1][0] - a[i] ) //买入的时候次数-1. 这里的是我们的约定,其实也可以反过来(卖出的时候-1次数)
第一维:表示第i天
第二维:表示当前最多进行k次交易
第三维:当前是否持有股票 1:持有,0:没有持有
递推式很容易理解,但是K值要分类讨论一下:
解法1: 当K为无穷大的时候,也就是可以无限交易的时候。无限交易的时候我们可以考虑贪心去解决,很显然,见好就收即可达到最优解。
解法2: 把上面的递推式令k=1,可得
dp[i][0] = max(dp[i-1][0],dp[i-1][1] + a[i]);
dp[i][1] = max(dp[i-1][1],dp[i-1][0] - a[i]);
class Solution {
public:
int maxProfit(vector<int>& a) {
int n = a.size();
int ans = 0;
for(int i = 1;i<n;++i){
if(a[i] > a[i-1])ans += a[i] - a[i-1];//见好就收即可达到最优解
}
return ans;
}
};
class Solution {
public:
// dp[i][0] = max(dp[i-1][0],dp[i-1][1] + a[i]);
// dp[i][1] = max(dp[i-1][1],dp[i-1][0] - a[i]);
int maxProfit(vector<int>& a) {
int n = a.size();
if(!n)return 0;
int dp_1,dp_0;
for(int i = 0;i<n;++i){
if(i == 0)
{
dp_1 = -a[i];
dp_0 = 0;
continue;
}
int tmp = dp_0;
dp_0 = max(dp_0,dp_1 + a[i]);
dp_1 = max(dp_1,tmp - a[i]);
}
return dp_0;
}
};
所以原问题的解题思路:
当k >= n/2,都可以认为我们可以无限交易,可以采用上述贪心的方式;
当k < n/2 ,采用上述动态规划思路
class Solution {
public:
int maxProfit(int k, vector<int> &prices) {
if (prices.empty()) return 0;
if (k >= prices.size()/2) return solveMaxProfit(prices);//贪心解决
int n = prices.size();
vector<vector<vector<int> > > dp(n,vector< vector<int> >(k+1,vector<int>(2,0)));
for(int i = 0;i<n;++i)
for(int j = 1;j<=k;++j)
{
if(i == 0)
{
dp[i][j][0] = 0;
dp[i][j][1] = -prices[i];
continue;
}
dp[i][j][0] = max(dp[i-1][j][0],dp[i-1][j][1] + prices[i]);
dp[i][j][1] = max(dp[i-1][j][1],dp[i-1][j-1][0] - prices[i]);
}
return dp[n-1][k][0];
}
int solveMaxProfit(vector<int> &prices) {
int res = 0;
for (int i = 1; i < prices.size(); ++i) {
if (prices[i] - prices[i - 1] > 0) {
res += prices[i] - prices[i - 1];
}
}
return res;
}
};
总结
leetcode这道题的变种有好多道:
只能进行一次交易:最低点买入,最高点卖出即可
含手续费:在上面的递推式加上手续费即可
我认为先写上面两道题才能看清这道题的本质!