给出每天股票的价格,设计一个算法计算出最大收益。可以最多买卖两个回合。而且卖出之后才能再买。
// 1
Input : [3, 3, 5, 0, 0, 3, 1, 4]
Output : 6
Explanation : 0-3, 1-4
// 2
Input : [1, 2, 3, 4, 5]
Output : 4
Explanation : 1-5
// 3
Input : [7, 6, 4, 3, 1]
Output : 0
Explanation : 0
构建一个大小为 l e n g t h ∗ ( l e n g t h + 1 ) length *(length +1) length∗(length+1)数组 d p dp dp,然后 d p [ i ] [ j ] ( i ∈ [ 0 , l e n g t h ) , j ∈ [ 0 , l e n g t h ] ) dp[i][j](i\in[0, length), j\in[0, length]) dp[i][j](i∈[0,length),j∈[0,length])表示以价格 p r i c e s [ i ] prices[i] prices[i]买入, p r i c e s [ j ] prices[j] prices[j]卖出的收益。而 d p [ i ] [ l e g n t h ] dp[i][legnth] dp[i][legnth]表示以价格 p r i c e s [ i ] prices[i] prices[i]买入,然后以某价格卖出的最高收益。然后从每个大于零 的收益开始寻找最大收益,对于任意 d p [ i ] [ j ] dp[i][j] dp[i][j],此时表示第一次交易,以 i i i价格买入, j j j价格卖出,然后在此基础上寻找第二次的最大收益,即寻找出 m a x ( d p [ x ] [ l e n g t h ] ) , x ∈ [ j , l e n g t h ) max(dp[x][length]), x\in[j, length) max(dp[x][length]),x∈[j,length), t e m p M a x = d p [ i ] [ j ] + m a x ( d p [ x ] [ l e n g t h ] ) tempMax = dp[i][j] + max(dp[x][length]) tempMax=dp[i][j]+max(dp[x][length]),对于每一行,都找到一个临时最大值,最后得出最大收益。
很明显时间复杂度 O ( n 3 ) O(n^3) O(n3),空间复杂度 O ( n 2 ) O(n^2) O(n2)。
class Solution {
public:
int maxProfit(vector& prices) {
int length = prices.size();
vector> dp(length, vector(length + 1, 0));
int max = 0;
for(int i = length - 1; i >= 0; -- i){
for(int j = i + 1; j < length; ++ j){
dp[i][j] = prices[j] - prices[i];
if(dp[i][j] > max)
max = dp[i][j];
}
dp[i][length] = max;
max = 0;
}
int temp;
for(int i = 0; i < length; ++ i){
for(int j = i + 1; j < length; ++ j){
if(dp[i][j] < 0)
continue;
temp = dp[i][j];
int temp_max = 0;
for(int k = j; k < length; ++ k){
if(temp_max < dp[k][length])
temp_max = dp[k][length];
}
temp += temp_max;
if(max < temp)
max = temp;
}
}
return max;
}
};
原链接
毫无疑问是用动态规划,可如何能找到递推式却是一个永恒的问题。有时候比女盆友还难找。
d p [ i ] [ j ] dp[i][j] dp[i][j]表示总共进行 i i i次交易,以第 j j j天结尾时的最高收益,那递推式
d p [ i ] [ j ] = m a x ( d p [ i ] [ j − 1 ] , p r i c e s [ j ] − p r i c e s [ x ] + d p [ i − 1 ] [ x ] ) x ∈ [ 0 , j − 1 ] d p [ i ] [ j ] = m a x ( d p [ i ] [ j − 1 ] , p r i c e s [ j ] + m a x ( d p [ i − 1 ] [ x ] − p r i c e s [ x ] ) ) d p [ 0 ] [ j ] = 0 d p [ i ] [ 0 ] = 0 dp[i][j] = max(dp[i][j-1], prices[j] - prices[x] + dp[i-1][x]) \quad x \in [0, j-1] \newline dp[i][j] = max(dp[i][j-1], prices[j] + max(dp[i-1][x]-prices[x] )) \newline dp[0][j] = 0 \newline dp[i][0] = 0 dp[i][j]=max(dp[i][j−1],prices[j]−prices[x]+dp[i−1][x])x∈[0,j−1]dp[i][j]=max(dp[i][j−1],prices[j]+max(dp[i−1][x]−prices[x]))dp[0][j]=0dp[i][0]=0
通过一定的代码优化,时间复杂度和空间复杂度为 O ( k ∗ n ) , O ( k ∗ n ) O(k * n), O(k * n) O(k∗n),O(k∗n)
class Solution {
public:
int maxProfit(vector& prices) {
int length = prices.size();
if(length == 0)
return 0;
int k = 2, maximum = 0, tmp_max;
vector> dp(k+1, vector(length, 0));
for(int i = 1; i < k+1; ++ i){
tmp_max = dp[i-1][0] - prices[0];
for(int j = 1; j < length; ++ j){
dp[i][j] = max(dp[i][j-1], prices[j] + tmp_max);
tmp_max = max(tmp_max, dp[i-1][j] - prices[j]);
maximum = max(dp[i][j], maximum);
}
}
return maximum;
}
};