无论是一次交易还是两次交易,原问题dp[1][n]满足,存在k∈[1,n],使得 dp[1][n] = dp[1][k] + dp[k][n]。则 dp[1][n] = max{ dp[1][k]+dp[k][n] }
dp[1][k] 与 dp[k][n] 可以通过遍历prices一次求得。具体如下:
dp[1][k]:从第一天到第k天可以获得的最大收益;dp[k][n]:从第k天到第n天可以获得的最大收益;
对于问题dp[1][k+1],当prices[k+1]是新的最小值时,dp[1][k+1]=0(同时更新当前所遇最小的prices);否则dp[1][k+1] = max{ dp[1][k],prices[k+1]-prices[lowest] };
对于问题dp[k][n]有类似的结论。
因此,程序仅需两次(或者说三次)遍历(访问) prices 即可求解 复杂度为O(n).
程序参考代码如下:
class Solution {
public:int maxProfit(vector<int> &prices) {
if(prices.size()==0) return 0;
vector<int> profit_buy( prices.size(),0); // best profit from ith day to the end dp[i][n]
vector<int> profit_sell(prices.size(),0); // best profit from 1st day to ith day dp[1][i]
int low=0; // index of lowest price from 1st day to ith day
int high=prices.size()-1; // index of highest price from ith day to nth day
for(int i=1;i<prices.size();i++){
// update dp[1][i]
if(prices[i] <prices[low] ) low = i;
profit_sell[i] = max(profit_sell[i-1] ,prices[i]-prices[low] );
int ind = prices.size()-i-1;
// update dp[i][n]
if(prices[ind]>prices[high]) high = ind;
profit_buy[ind] = max(profit_buy[ind+1],prices[high]-prices[ind]);
}
int ret = 0;
// dp[1][n] = max { dp[1][k]+dp[k][n] }
for(int k=0;k<prices.size();k++){
ret = max(ret,profit_sell[k] + profit_buy[k]);
}
return ret;
}
};
如有不当或待优化之处 望大家指出~