1. 只能买卖一次
贪心:
class Solution {
public int maxProfit(int[] prices) {
int minPrice = prices[0], profit = 0;
for (int i = 1; i < prices.length; i++) {
if (prices[i] < minPrice) {
minPrice = prices[i];
} else {
profit = Math.max(profit, prices[i] - minPrice);
}
}
return profit;
}
}
动态规划:
class Solution {
public int maxProfit(int[] prices) {
int len = prices.length;
int[][] dp = new int[len][2];
dp[0][1] = -prices[0];
for (int i = 1; i < len; 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[len - 1][0];
}
}
简化空间:
class Solution {
public int maxProfit(int[] prices) {
int len = prices.length;
int profit0 = 0, profit1 = - prices[0];
for (int i = 1; i < len; i++) {
profit0 = Math.max(profit0, profit1 + prices[i]);
profit1 = Math.max(profit1, -prices[i]);
}
return profit0;
}
}
2. 可以多次买卖
贪心:
class Solution {
public int maxProfit(int[] prices) {
int profit = 0;
for (int i = 1; i < prices.length; i++) {
if (prices[i] > prices[i - 1]) {
profit += prices[i] - prices[i - 1];
}
}
return profit;
}
}
动态规划:
class Solution {
public int maxProfit(int[] prices) {
int len = prices.length;
int[][] dp = new int[len][2];
dp[0][1] = -prices[0];
for (int i = 1; i < len; i++) {
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
dp[i][1] = Math.max(dp[i - 1][0] - prices[i], dp[i - 1][1]);
}
return dp[len - 1][0];
}
}
简化空间:
class Solution {
public int maxProfit(int[] prices) {
int len = prices.length;
int profit0 = 0, profit1 = -prices[0];
for (int i = 1; i < len; i++) {
int newProfit0 = Math.max(profit0, profit1 + prices[i]);
int newProfit1 = Math.max(profit1, profit0 - prices[i]);
profit0 = newProfit0;
profit1 = newProfit1;
}
return profit0;
}
}
3. 只能交易 2 次
动态规划:
class Solution {
public int maxProfit(int[] prices) {
int len = prices.length;
int[][][] dp = new int[len][3][2];
dp[0][1][0] = 0;
dp[0][1][1] = -prices[0];
dp[0][2][0] = 0;
dp[0][2][1] = -prices[0];
for (int i = 1; i < len; i++) {
dp[i][1][0] = Math.max(dp[i - 1][1][0], dp[i - 1][1][1] + prices[i]);
dp[i][1][1] = Math.max(dp[i - 1][1][1], dp[i - 1][0][0]-prices[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(dp[i - 1][2][1], dp[i - 1][1][0] - prices[i]);
}
return dp[len -1][2][0];
}
}
简化空间:
class Solution {
public int maxProfit(int[] prices) {
int buy1 = -prices[0], sell1 = 0;
int buy2 = -prices[0], sell2 = 0;
for (int i = 1; i < prices.length; 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;
}
}
4. 可以交易 k 次
class Solution {
public int maxProfit(int k, int[] prices) {
int len = prices.length;
if (len == 0 || len == 1) {
return 0;
}
if (k >= (len / 2)) { // 退化成 k 无穷大的情况
return maxProfit(prices);
}
int[][][] dp = new int[len][k + 1][2];
for (int i = 1; i <= k; i++) {
dp[0][i][0] = 0;
dp[0][i][1] = -prices[0];
}
for (int i = 1; i < len; i++) {
for (int j = 1; j <= k; j++) {
dp[i][j][0] = Math.max(dp[i - 1][j][0], dp[i - 1][j][1] + prices[i]);
dp[i][j][1] = Math.max(dp[i - 1][j][1], dp[i - 1][j - 1][0] - prices[i]);
}
}
return dp[len - 1][k][0];
}
public int maxProfit(int[] prices) {
int len = prices.length;
int[][] dp = new int[len][2];
dp[0][1] = -prices[0];
for (int i = 1; i < len; 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[len - 1][0];
}
}
简化空间:
class Solution {
public int maxProfit(int k, int[] prices) {
int len = prices.length;
if (len == 0 || len == 1) {
return 0;
}
if (k >= (len / 2)) { // 退化成 k 无穷大的情况
return maxProfit(prices);
}
int[][] dp = new int[k + 1][2];
for (int i = 1; i <= k; i++) {
dp[i][0] = 0;
dp[i][1] = -prices[0];
}
for (int i = 1; i < len; i++) {
for (int j = 1; j <= k; j++) {
dp[j][0] = Math.max(dp[j][0], dp[j][1] + prices[i]);
dp[j][1] = Math.max(dp[j][1], dp[j - 1][0] - prices[i]);
}
}
return dp[k][0];
}
public int maxProfit(int[] prices) {
int len = prices.length;
int profit0 = 0, profit1 = -prices[0];
for (int i = 1; i < len; i++) {
profit0 = Math.max(profit0, profit1 + prices[i]);
profit1 = Math.max(profit1, profit0 - prices[i]);
}
return profit0;
}
}
5. 买卖含冷冻期
动态规划:
class Solution {
public int maxProfit(int[] prices) {
if (prices == null || prices.length == 0 || prices.length == 1) {
return 0;
}
int len = prices.length;
int[][] dp = new int[len][2];
dp[0][1] = -prices[0];
for (int i = 1; i < len; 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], (i > 2 ? dp[i - 2][0] : 0) - prices[i]);
}
return dp[len - 1][0];
}
}
简化空间:
class Solution {
public int maxProfit(int[] prices) {
if (prices == null || prices.length == 0 || prices.length == 1) {
return 0;
}
int len = prices.length;
int profit0 = 0, preProfit0 = 0, profit1 = -prices[0];
for (int i = 1; i < len; i++) {
int nextProfit0 = Math.max(profit0, profit1 + prices[i]);
int nextProfit1 = Math.max(profit1, (i > 2 ? preProfit0 : 0) - prices[i]);
preProfit0 = profit0;
profit0 = nextProfit0;
profit1 = nextProfit1;
}
return profit0;
}
}
6. 买卖需要手续费
动态规划:
class Solution {
public int maxProfit(int[] prices, int fee) {
int len = prices.length;
if (len == 1) {
return 0;
}
int[][] dp = new int[len][2];
dp[0][1] = -prices[0] - fee;
for (int i = 1; i < len; 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] - fee);
}
return dp[len - 1][0];
}
}
简化空间:
class Solution {
public int maxProfit(int[] prices, int fee) {
int len = prices.length;
if (len == 1) {
return 0;
}
int profit0 = 0, profit1 = -prices[0] - fee;
for (int i = 1; i < len; i++) {
profit0 = Math.max(profit0, profit1 + prices[i]);
profit1 = Math.max(profit1, profit0 - prices[i] - fee);
}
return profit0;
}
}
重要参考:
https://leetcode-cn.com/circle/article/qiAgHn/
https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/solution/zui-jian-dan-2-ge-bian-liang-jie-jue-suo-71fe/