可无数次交易(必须交易完成后再进行)
因为可以多次交易,所以和1的区别只有状态方程不同(今天买股的情况)
如果今天结束后不持股,则可能是昨天持股,今天卖了,也可能是昨天就不持股。
如果今天结束后持股,可能是昨天就持股,也可能是昨天没持股,今天持股,这个就很只能买一次有区别了,由于是今天买的,而且能多次买,如果是买卖股票只能一次的话,那就只能-prices[i],为什么,因为之前的dp[i-1][0]肯定是0,因为都没买过,-prices[i]自然就是价格了。
而可多次交易的话,可能是昨天卖掉,今天买的,则昨天卖掉是有利润的尾dp[i-1][0],则今天买之后为dp[i-1][0]-prices[i];
class Solution {
public int maxProfit(int[] prices) {
int len = prices.length;
if (len < 2) {
return 0;
}
int[][] dp = new int[len][2];
dp[0][0] = 0;
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];
}
}
最多可交易两次,必须一次结束后再下一次
需要有一个新的值来记录交易次数,只关注发生交易的时候,不用关心没有发送交易的时候,所以定义交易次数为1和2的时候就行。
class Solution {
public int maxProfit(int[] prices) {
int len = prices.length;
if (len < 2) {
return 0;
}
int[][][] dp = new int[len][2][3];
dp[0][0][1]=0;
dp[0][1][1] = -prices[0];
dp[0][0][2] = 0;
dp[0][1][2] = -prices[0];
for (int i = 1; i < len; i++) {//不用管没有发生交易,只管发生交易的就可以
dp[i][0][1] =Math.max(dp[i-1][0][1],dp[i-1][1][1]+prices[i]);
dp[i][0][2] =Math.max(dp[i-1][0][2],dp[i-1][1][2]+prices[i]);
dp[i][1][1] =Math.max(dp[i-1][1][1],dp[i-1][0][0]-prices[i]);
dp[i][1][2] =Math.max(dp[i-1][1][2],dp[i-1][0][1]-prices[i]);
}
return dp[len-1][0][2];
}
}
最多可交易k次
因为一次交易最少要两天,所以交易的次数最多为k=len/2,如果k大于这个值,那就等于第二个问题,如果k小于这个值,就赋值k次初值,每一天都循环k次赋值即可。
class Solution {
public int maxProfit(int k, int[] prices) {
int len = prices.length;
if (len < 2) {
return 0;
}
if(k>=len/2)return maxProfit(prices);
int[][][] dp = new int[len][2][k+1];
for (int i = 1; i <= k; i++) {
dp[0][0][i] = 0;
dp[0][1][i] = -prices[0];
}
for (int i = 1; i < len; i++) {//不用管没有发生交易,只管发生交易的就可以
for(int j=k;j>0;j--){
dp[i][0][j] =Math.max(dp[i-1][0][j],dp[i-1][1][j]+prices[i]);
dp[i][1][j] =Math.max(dp[i-1][1][j],dp[i-1][0][j-1]-prices[i]);
}
}
return dp[len-1][0][k];
}
public int maxProfit(int[] prices) {
if (prices == null || prices.length == 0) {
return 0;
}
int length = prices.length;
int[][] dp = new int[length][2];
dp[0][0] = 0;
dp[0][1] = -prices[0];
for (int i = 1; i < 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]);
}
return dp[length - 1][0];
}
}
可交易无数次,但有冷冻期
在第一天卖掉股票后,第二天不能买,所以在今天有股票时,如果是今天买的,就不能算昨天没有了,而是算前天没有。
class Solution {
public int maxProfit(int[] prices) {
int len = prices.length;
if (len < 2) {
return 0;
}
int[][] dp = new int[len][2];
dp[0][0] = 0;
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, int fee) {
int len = prices.length;
if (len < 2) {
return 0;
}
int[][] dp = new int[len][2];
dp[0][0] = 0;
dp[0][1] = -fee-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]-fee);
}
return dp[len - 1][0];
}
}