可以有一次买入和一次卖出,买入必须在前。求最大收益。
使用贪心策略,假设第 i 轮进行卖出操作,买入操作价格应该在 i 之前并且价格最低。
Input: [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
Not 7-1 = 6, as selling price needs to be larger than buying price.
Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.
状态:一次买buy,一次卖sell,买则损失-price[i],卖则增加price[i]
收益=buy+price[i],buy默认为负数
buy=max(buy, -price[i])
sell=max(sell, buy+price[i])
第一天买的话,buy=-price[0],sell=0, 返回sell
class Solution {
public int maxProfit(int[] prices) {
if(prices.length<=1)
return 0;
int buy=-prices[0],sell=0;
for(int i=1;i<prices.length;i++){
buy=Math.max(buy,-prices[i]);
sell=Math.max(sell,buy+prices[i]);
}
return sell;
}
}
二、买股票二,可以无限次买入卖出
Input: [7,1,5,3,6,4]
Output: 7
Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4.
Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3.
Input: [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are
engaging multiple transactions at the same time. You must sell before buying again.
Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.
因为可以无限次买入卖出,则buy和sell之间就要比较
转移方程为:
buy=Math.max(buy, sell-price[i])
sell=Math.max(sell, buy+price[i])
class Solution {
public int maxProfit(int[] prices) {
if(prices.length<=1) return 0;
int buy=-prices[0],sell=0;
for(int i=1;i<prices.length;i++){
buy=Math.max(buy,sell-prices[i]);
sell=Math.max(sell, buy+prices[i]);
}
return sell;
}
}
三、最多两笔交易,两次买,两次卖,求最大收益
Input: [3,3,5,0,0,3,1,4]
Output: 6
Explanation: Buy on day 4 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.
Then buy on day 7 (price = 1) and sell on day 8 (price = 4), profit = 4-1 = 3.
Input: [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are
engaging multiple transactions at the same time. You must sell before buying again.
Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.
转移方程为:
第一次买卖:
fstBuy=Math.max(fstBuy, -price[i])
fstSell=Math.max(fstSell, fstBuy+price[i])
第二次买卖,受到第一次买卖的影响:
secBuy=Math.max(secBuy, fstSell-price[i])
secSell=Math.max(secSell, secBuy+price[i])
class Solution {
public int maxProfit(int[] prices) {
if(prices.length<=1) return 0;
int fstBuy=Integer.MIN_VALUE,fstSell=0;
int secBuy=Integer.MIN_VALUE,secSell=0;
for(int i=0;i<prices.length;i++){
fstBuy=Math.max(fstBuy,-prices[i]);
fstSell=Math.max(fstSell,fstBuy+prices[i]);
secBuy=Math.max(secBuy,fstSell-prices[i]);
secSell=Math.max(secSell,secBuy+prices[i]);
}
return secSell;
}
}
四、买股票四,增加参数k,限制最多k次交易:
Input: [2,4,1], k = 2
Output: 2
Explanation: Buy on day 1 (price = 2) and sell on day 2 (price = 4), profit = 4-2 = 2.
Input: [3,2,6,5,0,3], k = 2
Output: 7
Explanation: Buy on day 2 (price = 2) and sell on day 3 (price = 6), profit = 6-2 = 4.
Then buy on day 5 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.
k>=|prices| / 2,实际上相当于不限制交易次数
k<|prices|/2,循环的次数限制在k里面
class Solution {
public int maxProfit(int k, int[] prices) { // TLE
if (prices.length <= 1)
return 0;
// 假设|prices| == 4, 那么你顶多能做两次交易,如果k >= prices.length / 2,实际上就相当于不限制交易次数了
if (k >= prices.length / 2) {
int res = 0;
for (int i = 1; i < prices.length; i++) {
if (prices[i] > prices[i - 1]) {
res += prices[i] - prices[i - 1];
}
}
return res;
} else {
int[][] dp = new int[2][prices.length];
for (int i = 1; i <= k; i++) {
int tmpMax = dp[(i - 1) % 2][0] - prices[0];
for (int j = 1; j < prices.length; j++) {
dp[i % 2][j] = Math.max(dp[i % 2][j - 1], tmpMax + prices[j]);
tmpMax = Math.max(tmpMax, dp[(i - 1) % 2][j] - prices[j]);
}
}
return Math.max(dp[0][prices.length - 1], dp[1][prices.length - 1]);
}
}
}