题目列表
- 买卖股票的最佳时机1 可以买卖一次
- 买卖股票的最佳时机2 可以买卖多次
- 买卖股票的最佳时机3 最多买卖两次
- 买卖股票的最佳时机4 最大买卖k次
- 买卖股票的最佳时机含冷冻期 如题
- 买卖股票的最佳时机含手续费 如题
解答
class Solution {
public int maxProfit(int[] prices) {
//dp[i][0]表示持有股票所得的最大金额
//dp[i][1]表示不持有股票所得的最大金额
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(dp[i - 1][0],-prices[i]);
dp[i][1] = Math.max(dp[i - 1][1],prices[i] + dp[i - 1][0]);
}
return dp[prices.length - 1][1];
}
}
class Solution {
public int maxProfit(int[] prices) {
int[] dp = new int[2];
dp[0] = -prices[0];//dp[0]表示持有股票所得现金最大值
dp[1] = 0;
for(int i = 1;i <= prices.length;i++) {
//前一天持有
dp[0] = Math.max(dp[0],dp[1] - prices[i - 1]);
//前一天卖出
dp[1] = Math.max(dp[1],prices[i - 1] + dp[0]);
}
return dp[1];
}
}
class Solution {
public int maxProfit(int[] prices) {
//每一天有五种状态,
//0代表没有操作,1代表第一次买入,2代表第一次卖出,3代表第二次买入,4代表第二次卖出
//dp数组的定义为第i天所处状态所得利润最大值
int[][] dp = new int[prices.length][5];
//dp初始化,dp[0][1] = -prices[0],dp[0][2] = 0,dp[0][3]第二次买入该初始化多少呢?
//就相当于你在第一天买了又卖了,所以再买就是-prices[0],dp[0][4] = 0
dp[0][1] = -prices[0];
dp[0][3] = -prices[0];
for(int i = 1;i < prices.length;i++) {
dp[i][0] = dp[i - 1][0];
dp[i][1] = Math.max(dp[i - 1][1],dp[i - 1][0] - prices[i]);
dp[i][2] = Math.max(dp[i - 1][2],dp[i - 1][1] + prices[i]);
dp[i][3] = Math.max(dp[i - 1][3],dp[i - 1][2] - prices[i]);
dp[i][4] = Math.max(dp[i - 1][4],dp[i - 1][3] + prices[i]);
}
return dp[prices.length - 1][4];
}
}
class Solution {
public int maxProfit(int k, int[] prices) {
//dp数组定义;第i天状态为j时,所得利润的最大值
//j为0为不操作,1为第一次买入,2为第一次卖出...奇数买入,偶数卖出
if(prices.length == 0) {
return 0;
}
int[][] dp = new int[prices.length][2 * k + 1];
for(int j = 1;j < 2 * k;j+=2) {
dp[0][j] = -prices[0];
}
for(int i = 1;i < prices.length;i++) {
for(int j = 0;j < 2 * k - 1;j+=2) {
dp[i][j + 1] = Math.max(dp[i - 1][j + 1],dp[i - 1][j] - prices[i]);
dp[i][j + 2] = Math.max(dp[i - 1][j + 2],dp[i - 1][j + 1] + prices[i]);
}
}
return dp[prices.length - 1][2 * k];
}
}
class Solution {
public int maxProfit(int[] prices) {
//dp有四种状态:
//买入股票的状态:今天买入股票,或者昨天买入股票没有操作
//卖出股票的状态:昨天已经是卖出状态,或者前天卖出,冷冻一天,今天卖出
//冷冻状态,共四种状态
int[][] dp = new int[prices.length][4];
dp[0][0] = -prices[0];
for(int i = 1;i < prices.length;i++) {
dp[i][0] = Math.max(dp[i - 1][0],Math.max(dp[i - 1][3] - prices[i],dp[i - 1][1] - prices[i]));
dp[i][1] = Math.max(dp[i - 1][1],dp[i - 1][3]);
dp[i][2] = dp[i - 1][0] + prices[i];//达到今天卖出的状态,只能由昨天买入状态推导而来.
dp[i][3] = dp[i - 1][2];
}
return Math.max(dp[prices.length - 1][3],Math.max(dp[prices.length - 1][2],dp[prices.length - 1][1]));
}
}
class Solution {
public int maxProfit(int[] prices, int fee) {
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(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[prices.length - 1][1];
}
}
也可以用贪心
class Solution {
public int maxProfit(int[] prices, int fee) {
int n = prices.length;
int profit = 0;
int buy = prices[0] + fee;
for(int i = 1;i < n;i++) {
if(prices[i] + fee < buy) {
buy = prices[i] + fee;
}else if(prices[i] > buy) {
profit += prices[i] - buy;
buy = prices[i];
}
}
return profit;
}
}
总结
方法大差不差,有几道题只变了一点点,关键要明确状态的定义,进而写对递推方程.