法1:动态规划
想法1:
- 第 i 天时,将 prices[i] 与 prices[j] (j < i) 比较,意思是:在第 j 天买入,第 i 天卖出(也可能是第 j 天正持有一只股票,而不是购入新股)。会有以下两种情况出现
- prices[j] > prices[j - 1]:那么在第 j 天持有股票,或可以买入股票。
d p [ i ] = M a t h . m a x ( d p [ i ] , d p [ j ] + p r i c e s [ i ] − p r i c e s [ j ] , d p [ j ] ) dp[i] = Math.max(dp[i], dp[j] + prices[i] - prices[j], dp[j]) dp[i]=Math.max(dp[i],dp[j]+prices[i]−prices[j],dp[j])
dp[i]:之前的交易方式可能得到了更大利润
dp[j] + prices[i] - prices[j]:因为在第 j 天持有股票,或可以买入股票,所以可以用第 j 天的最大利润 + 从第 j 天到第 i 天的利润
dp[j]:如果 prices[i] - prices[j] < 0,则在第 i 天不卖出可以得到的利润更多,即 dp[j] - prices[j] < prices[j - 1]:那么在第 j 天之前一定卖出了。
d p [ i ] = M a t h . m a x ( d p [ i ] , d p [ j − 2 ] + p r i c e s [ i ] − p r i c e s [ j ] , d p [ j ] ) dp[i] = Math.max(dp[i], dp[j - 2] + prices[i] - prices[j], dp[j]) dp[i]=Math.max(dp[i],dp[j−2]+prices[i]−prices[j],dp[j])
dp[i]:之前的交易方式可能得到了更大利润
dp[j - 2] + prices[i] - prices[j]:第 j 天不是冷冻期,则在第 j - 2 天就卖出了,利润为 dp[j - 2],再加上从第 j 天到第 i 天的利润
dp[j]:第 j 天是冷冻期,则在第 j - 1 天卖出了,利润为dp[j](因为第 j 天是冷冻期,所以第 j 天最大利润就是dp[j - 1])
- 因为会遍历到 j - 1 和 j - 2,为防止数组dp访问错误,对于 j 为 0 和1的情况要另外处理
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function(prices) {
if(prices.length == 0) {
return 0;
}
var dp = [], i = 0, j = 0;
for(i = 0; i < prices.length; i++) {
dp[i] = 0;
}
for(i = 0; i < prices.length; i++) {
for(j = 0; j < i; j++) {
if(j == 0) {
dp[i] = Math.max(dp[i], prices[i] - prices[j]);
continue;
}
if(j == 1) {
dp[i] = Math.max(dp[i], prices[i] - prices[j] + dp[j], dp[j]);
continue;
}
if(prices[j] > prices[j - 1]) {
dp[i] = Math.max(dp[i], dp[j] + prices[i] - prices[j], dp[j]);
}
else {
dp[i] = Math.max(dp[i], dp[j - 2] + prices[i] - prices[j], dp[j]);
}
}
}
return dp[prices.length - 1];
};
想法2:
看了题解
- 对第 i 天进行分类:
- 冷却 or 非冷却
- 非冷却中:持股(包括买入) or 不持股(包括卖出)
- 冷却在卖出之后;卖出在买入之后;买入在冷却之后
具体看代码中的注释
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function(prices) {
if(prices.length == 0) {
return 0;
}
// 给第 i 天进行分类:
// 1. 冷却 or 非冷却
// C[i]表示第 i 天是冷却期的最大利润:第 i - 1 天卖出
// 2. 非冷却中:持股 or 不持股
// 持股:第 i 天买入,或继承前一天的股
// B[i]表示第 i 天:MAX{买入, 有股的观望}
// 不持股:第 i 天卖出,或前一天也没有股
// A[i]表示第 i 天:MAX{卖出, 没有股的观望}
var A = [], B = [], C = [], i = 0, N = prices.length;
for(i = 0; i < N; i++) {
A[i] = B[i] = C[i] = 0;
}
A[0] = 0, B[0] = -prices[0], C[0] = 0;
for(i = 1; i < N; i++) {
// A[i - 1]:继续没有股的观望
// B[i - 1] + prices[i]:卖出(卖出在买入或有股的观望之后)
// 不考虑C[i - 1]:因为卖出在买入B[i - 1]之后;没有股的观望即继承A[i - 1]的状态
A[i] = Math.max(A[i - 1], B[i - 1] + prices[i]);
// B[i - 1]:继续有股的观望
// C[i - 1] - prices[i]:在冷却期之后买入
// 不考虑A[i - 1]:因为卖出之后不能立马买入;没有股的观望之后的买入算入冷却期之后的买入
B[i] = Math.max(B[i - 1], C[i - 1] - prices[i]);
// 冷却期在卖出之后
C[i] = A[i - 1];
}
// 最后一天:不持股或冷却(也是不持股)的状态可能得到最大利润
return Math.max(A[N - 1], C[N - 1]);
};