121. Best Time to Buy and Sell Stock
题目链接:121. Best Time to Buy and Sell Stock
思路链接:代码随想录动态规划-买卖股票的最佳时机
思路
这道题比较快的解法可以用动态规划和贪心算法。这里主要阐述的是动态规划的思路。
第i天不持有股票不一定是在第i天卖出股票,也有可能之前已经卖出了。
- 确定dp数组
1.1 到第i天持有股票所拥有的最大现金 dp[i][0]
1.2 到第i天不持有股票拥有的最大现金 dp[i][1] - 确定递归数组
2.1 到第i天持有股票所拥有的最大现金 dp[i][0] = Math.max(dp[i - 1][0], -dp[i]);
要不就是昨天持有股票所得的最大现金,要不就是今天买入股票
2.2 到第i天不持有股票所拥有的最大现金 dp[i][1] = Math.max(prices[i] + dp[i - 1][0], dp[i - 1][1]);
要不就是今天卖出,要不就是昨天不持有股票拥有的最大现金 - 初始化数组
dp[0][0] -= prices[0]; 第0天持有股票所得的最大现金
dp[0][1] = 0; 到第0天不持有股票所拥有的最大现金 - 遍历顺序
- 打印数组
贪心算法比较简单,就是找左侧最小的值,从而得到当前遍历的最大差值,最终得到整个数组的最大差值。
Code
// 时间复杂度: O(n)
// 空间复杂度: O(n)
class Solution {
public int maxProfit(int[] prices) {
// 1. 确定dp数组
// 1.1 到第i天持有股票所拥有的最大现金 dp[i][0]
// 1.2 到第i天不持有股票拥有的最大现金 dp[i][1]
int[][] dp = new int[prices.length][2];
// 2. 确定递归数组
// 2.1 到第i天持有股票所拥有的最大现金 dp[i][0] = Math.max(dp[i - 1][0], -dp[i]); 要不就是昨天持有股票所得的最大现金,要不就是今天买入股票
// 2.2 到第i天不持有股票所拥有的最大现金 dp[i][1] = Math.max(prices[i] + dp[i - 1][0], dp[i - 1][1]); 要不就是今天卖出,要不就是昨天不持有股票拥有的最大现金
// 3. 初始化数组
dp[0][0] -= prices[0]; // 第0天持有股票所得的最大现金
dp[0][1] = 0; // 到第0天不持有股票所拥有的最大现金
// 4. 遍历顺序
for (int i = 1; i < prices.length; i++) {
dp[i][0] = Math.max(dp[i - 1][0], 0 - prices[i]);
dp[i][1] = Math.max(prices[i] + dp[i - 1][0], dp[i - 1][1]);
// 5. 打印数组
// for (int[] row : dp) {
// for (int item : row) {
// System.out.print(item + " ");
// }
// System.out.println("");
// }
}
return dp[prices.length - 1][1];
}
}
// 时间复杂度: O(n)
// 空间复杂度: O(1)
class Solution {
public int maxProfit(int[] prices) {
// 贪心算法
int low = Integer.MAX_VALUE;
int result = 0;
for (int i = 0; i < prices.length; i++) {
low = Math.min(low, prices[i]);
result = Math.max(result, prices[i] - low);
}
return result;
}
}
122. Best Time to Buy and Sell Stock II
题目链接:122. Best Time to Buy and Sell Stock II
思路链接:代码随想录动态规划-买卖股票的最佳时机II
思路
贪心算法之间已经写过文章了
动态规划的dp数组与上一题一样,只不过这一题可以买卖很多次。递推公式发生了变化:
- 到第i天时持有股票拥有的最大金额为dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] - prices[i]);
- 到第i天时不持有股票拥有的最大金额为dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] + prices[i]);
Code
class Solution {
public int maxProfit(int[] prices) {
// 1. 定义dp数组
// 1.1 到第i天时持有股票拥有的最大金额为dp[i][0]
// 1.2 到第i天时不持有股票拥有的最大金额为dp[i][1]
int[][] dp = new int[prices.length][2];
// 2. 确定递推公式
// 2.1 到第i天时持有股票拥有的最大金额为dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] - prices[i]);
// 2.2 到第i天时不持有股票拥有的最大金额为dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] + prices[i]);
// 3. 初始化数组
dp[0][0] -= prices[0];
dp[0][1] = 0;
// 4. 遍历顺序
for (int i = 1; i < prices.length; i++) {
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] - prices[i]);
dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] + prices[i]);
// 5. 打印数组
// for (int[] row : dp) {
// for (int item : row) {
// System.out.print(item + " ");
// }
// System.out.println("");
// }
}
return dp[prices.length - 1][1];
}
}