股票买卖最佳时机
文章目录
- 股票买卖最佳时机
- 一、[121. 买卖股票的最佳时机](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/)
- 二、[122. 买卖股票的最佳时机 II](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/)
- 三、[123. 买卖股票的最佳时机 III](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/)
- 四、[309. 最佳买卖股票时机含冷冻期](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/)
- 五、[188. 买卖股票的最佳时机 IV](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iv/)
- 六、[714. 买卖股票的最佳时机含手续费](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/)
一、121. 买卖股票的最佳时机
在一个数组中找到两个值:后一个值减去前一个值,差值最大。
解法一:暴力法,(时间超限制)
public int maxProfit(int[] prices) {
int res = 0;
for (int i=0; i<prices.length-1; i++) {
for (int j=i+1; j<prices.length; j++) {
if (prices[j]-prices[i]>res) {
res = prices[j] - prices[i];
}
}
}
return res;
}
解法二:一次遍历
public int maxProfit(int[] prices) {
int minV = Integer.MAX_VALUE;
int res = 0;
for (int i=0; i<prices.length; i++) {
if (minV>prices[i]) {
minV = prices[i];
}else if (prices[i]-minV>res) {
res = prices[i]-minV;
}
}
return res;
}
解法三:动态规划(二维数组)
public int maxProfit(int[] prices) {
int n = prices.length;
if (n<2) return 0;
// dp[i][0] 不持有股票、dp[i][1] 持有股票
int[][] dp = new int[n][2];
dp[0][0] = 0;
dp[0][1] = 0-prices[0];
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], -prices[i]);
}
return dp[n-1][0];
}
解法四:动态规划(空间复杂度的优化一)
public int maxProfit(int[] prices) {
int n = prices.length;
if (n<2) return 0;
int[][] dp = new int[2][2];
// dp[i][0] 不持有股票, dp[i][1] 持有股票
dp[0][0] = 0;
dp[0][1] = -prices[0];
for (int i=1; i<n; i++) {
dp[i%2][0] = Math.max(dp[(i-1)%2][0], dp[(i-1)%2][1]+prices[i]);
dp[i%2][1] = Math.max(-prices[i], dp[(i-1)%2][1]);
}
return dp[(n+1)%2][0];
}
解法五:动态规划(空间复杂度的优化二)
public int maxProfit(int[] prices) {
int n = prices.length;
if (n<2) return 0;
int notGP = 0;
int hasGP = -prices[0];
for (int i=1; i<n; i++) {
notGP = Math.max(notGP, hasGP+prices[i]);
hasGP = Math.max(-prices[i], hasGP);
}
return notGP;
}
二、122. 买卖股票的最佳时机 II
2.1 解法一:贪心算法
public int maxProfit(int[] prices) {
int n = prices.length;
if (n<2) return 0;
int res = 0;
for (int i=1; i<n; i++) {
if (prices[i]>prices[i-1]) {
res += prices[i]-prices[i-1];
}
}
return res;
}
2.2 解法二:动态规划
dp[i][0] 持有现金;dp[i][1] 持有股票
public int maxProfit(int[] prices) {
int n = prices.length;
if (n<2) return 0;
int[][] dp = new int[n][2];
// 持有股票
dp[0][0] = 0;
// 持有现金
dp[0][1] = -prices[0];
for (int i=1; i<n; 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]);
}
return dp[n-1][0];
}
2.3 解法三:动态规划(空间复杂度优化)
public int maxProfit(int[] prices) {
int n = prices.length;
if (n<2) return 0;
int notGP = 0;
int hasGP = -prices[0];
for (int i=1; i<n; i++) {
int tNotGP = notGP;
notGP = Math.max(notGP, hasGP+prices[i]);
hasGP = Math.max(hasGP, tNotGP-prices[i]);
}
return notGP;
}
三、123. 买卖股票的最佳时机 III
3.1 解法一:转换成第一题(时间超限制)
public int maxProfit(int[] prices) {
int n = prices.length;
if (n<2) return 0;
int res = 0;
for (int i=1; i<n; i++) {
int leftRes = subMax(0, i, prices);
int rightRes = subMax(i+1, n-1, prices);
res = Math.max(res, leftRes + rightRes);
}
return res;
}
/**
* 查询自结果
*/
private int subMax(int lo, int hi, int[] prices) {
if (lo>=hi) return 0;
int notGP=0;
int hasGP=-prices[lo];
for (int i=lo+1; i<=hi; i++) {
notGP = Math.max(notGP, hasGP+prices[i]);
hasGP = Math.max(hasGP, -prices[i]);
}
return notGP;
}
3.2 解法二:动态规划
public int maxProfit(int[] prices) {
int n = prices.length;
if (n<2) return 0;
int buy1 = -prices[0], sell1 = 0;
int buy2 = -prices[0], sell2 = 0;
for (int i=1; i<n; i++) {
buy1 = Math.max(buy1, -prices[i]);
sell1 = Math.max(sell1, buy1+prices[i]);
buy2 = Math.max(buy2, sell1-prices[i]);
sell2 = Math.max(sell2, buy2+prices[i]);
}
return sell2;
}
四、309. 最佳买卖股票时机含冷冻期
4.1 动态规划
public int maxProfit(int[] prices) {
int n = prices.length;
if (n<2) return 0;
int[][] dp = new int[n][3];
// dp[i][0] 持有股票
// dp[i][1] 今天卖出后,处于冷冻期
// dp[i][2] 不持有股票,并且不处于冷冻期
dp[0][0] = -prices[0];
dp[0][1] = 0;
dp[0][2] = 0;
for (int i=1; i<n; i++) {
dp[i][0] = Math.max(dp[i-1][0], dp[i-1][2]-prices[i]);
dp[i][1] = dp[i-1][0] + prices[i];
dp[i][2] = Math.max(dp[i-1][1], dp[i-1][2]);
}
return Math.max(dp[n-1][1], dp[n-1][2]);
}
4.2 动态规划(空间优化)
public int maxProfit(int[] prices) {
int n = prices.length;
if (n<2) return 0;
// 今天买入股票
int hasGP = -prices[0];
// 今天售出股票
int sellGP = 0;
// 今天不持有股票
int notGP = 0;
for (int i=1; i<n; i++) {
int tempHasGP = hasGP;
int tempSellGP = sellGP;
hasGP = Math.max(hasGP, notGP-prices[i]);
sellGP = tempHasGP + prices[i];
notGP = Math.max(tempSellGP, notGP);
}
return Math.max(sellGP, notGP);
}
五、188. 买卖股票的最佳时机 IV
5.1 动态规划:是123. 买卖股票的最佳时机 III 问题的扩展
public int maxProfit(int k, int[] prices) {
int n = prices.length;
if (n<2 || k<1) return 0;
// dp[i][0] 第i次买, dp[i][1] 第i次卖
int[][] dp = new int[k][2];
for (int j=0;j<k; j++) {
dp[j][0] = -prices[0];
dp[j][1] = 0;
}
for (int i=1; i<n; i++) {
dp[0][0] = Math.max(dp[0][0], -prices[i]);
dp[0][1] = Math.max(dp[0][1], dp[0][0]+prices[i]);
for (int j=1; j<k; j++) {
dp[j][0] = Math.max(dp[j-1][1]-prices[i], dp[j][0]);
dp[j][1] = Math.max(dp[j][1], dp[j][0]+prices[i]);
}
}
return dp[k-1][1];
}
六、714. 买卖股票的最佳时机含手续费
6.1 动态规划
public int maxProfit(int[] prices, int fee) {
int n = prices.length;
if (n<2) return 0;
// dp[i][0] 不持有股票, dp[i][1] 持有股票
int[][] dp = new int[n][2];
dp[0][0] = 0;
dp[0][1] = -prices[0];
for (int i=1; i<n; i++) {
dp[i][0] = Math.max(dp[i-1][1]+prices[i]-fee, dp[i-1][0]);
dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0]-prices[i]);
}
return Math.max(dp[n-1][0], dp[n-1][1]);
}
6.2 动态规划(空间优化)
public int maxProfit(int[] prices, int fee) {
int n = prices.length;
if (n<2) return 0;
int hasGP = -prices[0];
int notGP = 0;
for (int i=1; i<n; i++) {
int t = hasGP;
hasGP = Math.max(hasGP, notGP-prices[i]);
notGP = Math.max(notGP, t+prices[i]-fee);
}
return Math.max(hasGP, notGP);
}
本文深入解析了六个股票买卖问题的最优时机算法,包括121-123题的动态规划解法,以及309、188和714题的扩展,展示了如何利用贪心、空间优化等技巧求解。
843

被折叠的 条评论
为什么被折叠?



