309. Best Time to Buy and Sell Stock with Cooldown
2016-07-09 22:03
281 查看
Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times) with the following restrictions:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
After you sell your stock, you cannot buy stock on next day. (ie, cooldown 1 day)
Example:
摘自:https://discuss.leetcode.com/topic/30431/easiest-java-solution-with-explanations/2
1. Define States
To represent the decision at index i:
of transaction is ending with a buy.
of transaction is ending with a sell.
To clarify:
Till index
must happen and must be the last action. It may not happen at index
It may happen at
In the end
For special case no transaction at all, classify it as
so that in the end, we can still return
2. Define Recursion
at
We cannot sell at
because of cooldown.
at
A great explanation. I think the definitions of
be refined to these:
end with buying on day
with buying on a day before
then.
end with selling on day
with selling on a day before
then.
So we get the following formula:
3. Optimize to O(1) Space
DP solution only depending on
Let
Let
Then arrays turn into Fibonacci like recursion:
4. Write Code in 5 Minutes
First we define the initial states at
We can buy. The max profit at
with a buy is
We cannot sell. The max profit at
with a sell is
Here is my solution. Hope it helps!
-------------------------------------------------------------------------------------
自己想的O(N^2)的方法。。。
对于某天来说,如果是休息,最大利润和前一天相同,否则的话要做决策,不卖的话跟前一天一样。卖的话依次看看i-1天,i-2天……的情况,
如果i-k天做了卖出操作,那么i-k+1天就要休息,最大利润就是今天价格减去[i-k+2 ,i-1]的最小值,如果i-k-1天做了卖出操作,最大利润就是今天价格减去[i-k+1 ,i-1]的最小值,如果i-k和i-k-1天都没有做卖出操作,最大利润是今天价格减去[i-k,i-1]的最小值。怎么知道哪一天是卖了的呢?另外开辟一个数组记录,dp的过程中如果第i天利润最大不是和i-1天相同,说明是卖出了的,标记这一天就行了。
public int maxProfit(int[] prices)
{
int len=prices.length;
if(len<2)
return 0;
int[] dp=new int[len];
int[] aux=new int[len];
SegmentTree2_1 sgt=new SegmentTree2_1(len);
sgt.build(1, len, 1, prices);
dp[0]=0;
dp[1]=prices[1]>prices[0]?prices[1]-prices[0]:0;
for(int i=2;i<len;i++)
{
int max=dp[i-1];
for(int j=i-2;j>=0;j--)
{
int k;
if(aux[j]==1)
k=j+2;
else if(j-1>=0&&aux[j-1]==1)
k=j+1;
else {
k=j;
}
int stepmin=(int) sgt.query(k+1, i, 1, len, 1);
max=Math.max(max, dp[j]+prices[i]-stepmin);
}
if(max!=dp[i-1])
aux[i]=1;
dp[i]=max;
}
return dp[len-1];
}
}
cl
a0da
ass SegmentTree2_1
{
private long[] ele;
int cnt=0;
public SegmentTree2_1(int maxn)
{
ele = new long[maxn << 2];
}
public void build(int l, int r, int rt,int[] arr)
{
if(arr.length<1)
return ;
if (l == r)
{
ele[rt] = arr[cnt++];
return;
}
int m = (l + r) >> 1;
build(l, m, rt << 1,arr);
build(m + 1, r, rt << 1 | 1,arr);
PushUP(rt);
}
private void PushUP(int rt)
{
ele[rt] = Math.min(ele[rt << 1] , ele[rt << 1 | 1]);
}
public long query(int L, int R, int l, int r, int rt)
{
if (L <= l && r <= R)
return ele[rt];
int m = (l + r) >> 1;
long ret = Integer.MAX_VALUE;
if (L <= m)
ret = Math.min(ret,query(L, R, l, m, rt << 1));
if (R > m)
ret = Math.min(ret,query(L, R, m + 1, r, rt << 1 | 1));
return ret;
}
}
Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times) with the following restrictions:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
After you sell your stock, you cannot buy stock on next day. (ie, cooldown 1 day)
Example:
prices = [1, 2, 3, 0, 2] maxProfit = 3 transactions = [buy, sell, cooldown, buy, sell]
摘自:https://discuss.leetcode.com/topic/30431/easiest-java-solution-with-explanations/2
1. Define States
To represent the decision at index i:
buy[i]: Max profit till index i. The series
of transaction is ending with a buy.
sell[i]: Max profit till index i. The series
of transaction is ending with a sell.
To clarify:
Till index
i, the buy / sell action
must happen and must be the last action. It may not happen at index
i.
It may happen at
i - 1, i - 2, ... 0.
In the end
n - 1, return
sell[n - 1]. Apparently we cannot finally end up with a buy. In that case, we would rather take a rest at
n - 1.
For special case no transaction at all, classify it as
sell[i],
so that in the end, we can still return
sell[n - 1]. Thanks @alex153 @kennethliaoke @anshu2.
2. Define Recursion
buy[i]: To make a decision whether to buy
at
i, we either take a rest, by just using the old decision at
i - 1, or sell at/before
i - 2, then buy at
i,
We cannot sell at
i - 1, then buy at
i,
because of cooldown.
sell[i]: To make a decision whether to sell
at
i, we either take a rest, by just using the old decision at
i - 1, or buy at/before
i - 1, then sell at
i.
A great explanation. I think the definitions of
buy[i]and
sell[i]can
be refined to these:
buy[i]: Maximum profit which
end with buying on day
ior end
with buying on a day before
iand takes rest until the day
isince
then.
sell[i]: Maximum profit which
end with selling on day
ior end
with selling on a day before
iand takes rest until the day
isince
then.
So we get the following formula:
buy[i] = Math.max(buy[i - 1], sell[i - 2] - prices[i]); sell[i] = Math.max(sell[i - 1], buy[i - 1] + prices[i]);
3. Optimize to O(1) Space
DP solution only depending on
i - 1and
i - 2can be optimized using O(1) space.
Let
b2, b1, b0represent
buy[i - 2], buy[i - 1], buy[i]
Let
s2, s1, s0represent
sell[i - 2], sell[i - 1], sell[i]
Then arrays turn into Fibonacci like recursion:
b0 = Math.max(b1, s2 - prices[i]); s0 = Math.max(s1, b1 + prices[i]);
4. Write Code in 5 Minutes
First we define the initial states at
i = 0:
We can buy. The max profit at
i = 0ending
with a buy is
-prices[0].
We cannot sell. The max profit at
i = 0ending
with a sell is
0.
Here is my solution. Hope it helps!
public int maxProfit(int[] prices) {
if(prices == null || prices.length <= 1) return 0;
int b0 = -prices[0], b1 = b0;
int s0 = 0, s1 = 0, s2 = 0;
for(int i = 1; i < prices.length; i++) {
b0 = Math.max(b1, s2 - prices[i]); s0 = Math.max(s1, b1 + prices[i]);b1 = b0; s2 = s1; s1 = s0;
}
return s0;
}
-------------------------------------------------------------------------------------
自己想的O(N^2)的方法。。。
对于某天来说,如果是休息,最大利润和前一天相同,否则的话要做决策,不卖的话跟前一天一样。卖的话依次看看i-1天,i-2天……的情况,
如果i-k天做了卖出操作,那么i-k+1天就要休息,最大利润就是今天价格减去[i-k+2 ,i-1]的最小值,如果i-k-1天做了卖出操作,最大利润就是今天价格减去[i-k+1 ,i-1]的最小值,如果i-k和i-k-1天都没有做卖出操作,最大利润是今天价格减去[i-k,i-1]的最小值。怎么知道哪一天是卖了的呢?另外开辟一个数组记录,dp的过程中如果第i天利润最大不是和i-1天相同,说明是卖出了的,标记这一天就行了。
public int maxProfit(int[] prices)
{
int len=prices.length;
if(len<2)
return 0;
int[] dp=new int[len];
int[] aux=new int[len];
SegmentTree2_1 sgt=new SegmentTree2_1(len);
sgt.build(1, len, 1, prices);
dp[0]=0;
dp[1]=prices[1]>prices[0]?prices[1]-prices[0]:0;
for(int i=2;i<len;i++)
{
int max=dp[i-1];
for(int j=i-2;j>=0;j--)
{
int k;
if(aux[j]==1)
k=j+2;
else if(j-1>=0&&aux[j-1]==1)
k=j+1;
else {
k=j;
}
int stepmin=(int) sgt.query(k+1, i, 1, len, 1);
max=Math.max(max, dp[j]+prices[i]-stepmin);
}
if(max!=dp[i-1])
aux[i]=1;
dp[i]=max;
}
return dp[len-1];
}
}
cl
a0da
ass SegmentTree2_1
{
private long[] ele;
int cnt=0;
public SegmentTree2_1(int maxn)
{
ele = new long[maxn << 2];
}
public void build(int l, int r, int rt,int[] arr)
{
if(arr.length<1)
return ;
if (l == r)
{
ele[rt] = arr[cnt++];
return;
}
int m = (l + r) >> 1;
build(l, m, rt << 1,arr);
build(m + 1, r, rt << 1 | 1,arr);
PushUP(rt);
}
private void PushUP(int rt)
{
ele[rt] = Math.min(ele[rt << 1] , ele[rt << 1 | 1]);
}
public long query(int L, int R, int l, int r, int rt)
{
if (L <= l && r <= R)
return ele[rt];
int m = (l + r) >> 1;
long ret = Integer.MAX_VALUE;
if (L <= m)
ret = Math.min(ret,query(L, R, l, m, rt << 1));
if (R > m)
ret = Math.min(ret,query(L, R, m + 1, r, rt << 1 | 1));
return ret;
}
}
相关文章推荐
- 繁简体(GB<=>Big5)字符串互转的JAVA方式实现
- [华为OJ] 字符串加解密
- HTML5基础知识
- 获取Android Studio的SHA1
- 复数类的设计及加减法的实现(Complex Numbers)
- Codeforces Round #358 (Div. 2) D. Alyona and Strings(DP)
- hibernate中Query的list和iterator区别(续)
- Windows进程通信 -- 共享内存
- 华为机试--最高分是多少
- Solr/SolrCloud SolrConfigHandler详解
- 华为机试题【11】-报数删除人
- iOS多线程技术-上
- 华为机试题【11】-报数删除人
- 华为机试题【11】-报数删除人
- 华为机试题【11】-报数删除人
- 1、linux软件包管理
- Word Search
- 【自定义View系列】04--谈谈事件分发
- MFC标题和文字的修改
- [C#6] 7-索引初始化器