I:
方法一:维护一个最小值vally,表示截止到第i天时所出现过的最低价。计算第i天的股价与这个vally的差值,保留最大值
class Solution {
public:
int maxProfit(vector<int> &prices) {
int minVal = 0x7fffffff;
int maxDiff = 0;
for(int i = 0; i < prices.size();i++){
minVal = min(minVal,prices[i]);
maxDiff = max(maxDiff,prices[i] - minVal);
}
maxDiff = max(0,maxDiff);
return maxDiff;
}
};
方法二:
计算prices[]后一天和前一天的差,得到差分数组。然后可以用最大子段和DP求解。
class Solution {
public:
int maxProfit(vector<int> &prices) {
int n = prices.size();
if(n==0)return 0;
for(int i = n-1;i >= 1 ;i--){
prices[i] = prices[i] - prices[i-1];
}
prices[0] = 0;
int* dp = new int[n];
memset(dp,0,sizeof(int)*n);
int res = 0;
for(int i = 1 ;i < n;i++){
dp[i] = max(0,dp[i-1]) + prices[i];
res = max(res,dp[i]);
}
return res;
}
};
II:
class Solution {
public:
int maxProfit(vector<int> &prices) {
int n = prices.size();
if(n==0)return 0;
int* dp = new int[n];
memset(dp,0,sizeof(int)*n);
for(int i = 1; i < n ;i++){
dp[i] = dp[i-1] + max(0,prices[i] - prices[i-1]);
}
return dp[n-1];
}
};
用DP的思想来看,这个问题是具有最优子结构的。前i天赚的钱,可以由前i-1天的交易赚的钱计算得到,取决于第i天的行为。
由于股票可以当天卖了马上再买,因此我们可以用dp[i-1]来表示在第i-1天清仓的前提下,前i-1天能赚到的最多的钱。然后再根据第i天的股价决定是否要再买入。
III:
方法一:
枚举i从0到n,将prices[]分成[0,i]和[i,n-1]两段
对每一段采用I中的算法,f[i]表示从0到i天所能获得的最大利润,g[i]表示从i到n-1天所能获得的最大利润。再求max(f[i]+g[i])即可。
注意在求g[i]的时候,要从后向前算,维护的是从n-1到i出现过的最大值peak,而不是最小值vally。
class Solution {
public:
int maxProfit(vector<int> &prices) {
int n = prices.size();
if(!n)return 0;
int f[n];
int g[n];
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
int vally = prices[0];
int peak = prices[n-1];
for(int i = 1;i < n;i++){
vally = min(vally,prices[i]);
f[i] = max(f[i-1],prices[i] - vally);
}
for(int i = n - 2; i >= 0; i--){
peak = max(peak,prices[i]);
g[i] = max(g[i+1],peak - prices[i]);
}
int res= -1;
for(int i = 0;i < n;i++){
res = max(res,f[i]+g[i]);
}
return res;
}
};
方法二:
转化成差分数组,求最大M子段和,M=2。