121. Best Time to Buy and Sell Stock
- 方法1: Greedy
- min: min(min, prices[i])
- profit: max(profit, prices[i]-min) prices[i]-min保证了prices[i]一定是在min之后出现的价格
- Time Complexity: O(n)
- Space Complexity: O(1)
- 方法2: dp
-
dp[i][0] = 第i天持有股票所得最多现金。本题中只能买卖一次,持有股票之后哪还有现金呢? 第i天买入股票现金就是 -prices[i],是一个负数。
-
dp[i][1] = 第i天不持有股票所得最多现金
-
注意“持有”:1. 当天“买入” or 2. 之前买入,今天保持持有的状态
-
注意“不持有”:1. 当天“卖出” or 2. 之前就卖出了,今天保持不持有的状态
-
公式:
-
dp[i][0] = max(dp[i - 1][0], -prices[i]); = max(之前买入, 当天买入)
-
注意当天买入不能是dp[i-1][1]-prices[i]因为只能买卖一次,今天买入的话之前profit一定为0
-
-
dp[i][1] = max(dp[i - 1][1], prices[i]+dp[i-1][0]); = max(之前卖出, 当天卖出)
-
-
最后return dp[prices.length-1][1]一定大于dp[prices.length-1][0] 因为本题中不持有股票状态所得金钱一定比持有股票状态得到的多。
- Time Complexity: O(n)
- Space Complexity: O(n) -> 可以优化成O(1)
// O(n)
class Solution {
public int maxProfit(int[] prices) {
int[][] dp = new int[prices.length][2];
dp[0][0] = -prices[0]; // 持有
dp[0][1] = 0; // 不持有
for (int i=1; i<prices.length; i++) {
dp[i][0] = Math.max(-prices[i], dp[i-1][0]);
dp[i][1] = Math.max(prices[i]+dp[i-1][0], dp[i-1][1]);
}
return dp[prices.length-1][1];
}
}
// O(1)
class Solution {
public int maxProfit(int[] prices) {
int[] dp = new int[2];
dp[0] = -prices[0]; // have stock on day i
dp[1] = 0; // don't have stock on day i
for (int i=1; i<prices.length; i++) {
int temp = dp[0];
dp[0] = Math.max(-prices[i], dp[0]);
dp[1] = Math.max(prices[i]+temp, dp[1]);
}
return dp[1];
}
}
122. Best Time to Buy and Sell Stock ii
- 唯一和上一题的区别在于一支股票可以买卖好几次(但是还是不能同时持有,而且只有一支股票)
- 所以对于dp[i][0]持有股票的情况:
- 1. 之前已经持有dp[i-1][0]
- 2. 今天买入股票 dp[i-1][1] - prices[i] 之前没有持有股票的现金(可能有过交易有profit)-第i天股票价格
// O(n)
class Solution {
public int maxProfit(int[] prices) {
int[][] dp = new int[prices.length][2];
dp[0][0] = -prices[0]; // have
dp[0][1] = 0; // don't have
for (int i=1; i<prices.length; i++) {
dp[i][0] = Math.max(dp[i-1][1]-prices[i], dp[i-1][0]);
dp[i][1] = Math.max(dp[i-1][0]+prices[i], dp[i-1][1]);
}
return dp[prices.length-1][1];
}
}
// O(1)
class Solution {
public int maxProfit(int[] prices) {
int[] dp = new int[2];
dp[0] = -prices[0]; // have
dp[1] = 0; // don't have
for (int i=1; i<prices.length; i++) {
int temp = dp[0];
dp[0] = Math.max(dp[1]-prices[i], dp[0]);
dp[1] = Math.max(temp+prices[i], dp[1]);
}
return dp[1];
}
}