博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【LeetCode & 剑指offer刷题】动态规划与贪婪法题11:121. Best Time to Buy and Sell Stock(系列)...
阅读量:5050 次
发布时间:2019-06-12

本文共 7713 字,大约阅读时间需要 25 分钟。

 

Best Time to Buy and Sell Stock(系列)

121
.
 
Best Time to Buy and Sell Stock
Say you have an array for which the
 
i
th
 
element is the price of a given stock on day
 
i
.
If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.
Note that you cannot sell a stock before you buy one.
Example 1:
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.
Example 2:
Input:
[7,6,4,3,1]
Output:
0
Explanation:
In this case, no transaction is done, i.e. max profit = 0.
 
//
股票买卖问题(在指定区间仅可以一次买入,一次卖出或者不交易)
//
方法一:暴力法,找买入卖出数据对(
a[i] a[j]
),并满足
i<j
时间复杂度
O
n^2
//
方法二:一次遍历,找最大值和最小值,时间复杂度
O
n
)类似:
class
Solution
{
public
:
   
int
maxProfit
(
vector
<
int
>&
prices
)
   
{
       
if
(
prices
.
empty
())
return
0
;
       
int
minprice
=
prices
[
0
];
//
初始化最低价格
       
//int maxprice = prices[0];//
初始化最高价格
,
如果这样,还需判断最低价格和最高价格的先后位置
       
int
maxprofit
=
0
;
//
初始化最大收益
       
       
for
(
int
p
:
prices
)
//
这里用
int
比用
auto
2ms
左右
       
{
           
if
(
p
<
minprice
)
minprice
=
p
;
           
else
if
(
p
-
minprice
>
maxprofit
)
maxprofit
=
p
-
minprice
;
//
计算最大收益,无需判断最高价格和最低价格的先后位置
       
}
       
return
maxprofit
;
   
}
};
//
方法三:转化为涨跌数组,就可以转化为最大子数组问题了,可以用分治法,略显麻烦
 
122
.
 
Best Time to Buy and Sell Stock II
Say you have an array for which the
 
i
th
 
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 (i.e., buy one and sell one share of the stock multiple times).
Note:
 
You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again).
Example 1:
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.
Example 2:
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.
Example 3:
Input:
[7,6,4,3,1]
Output:
0
Explanation:
In this case, no transaction is done, i.e. max profit = 0.
 
 
//
股票买卖问题
2(
可以在指定区间买卖多次,不能出现连续买
)
//
方法:可以转成涨跌数组,将所有正数相加
(
或者直接判断相邻数大小,算上
a[i]>a[i-1]
的情况
)
class
Solution
{
public
:
   
int
maxProfit
(
vector
<
int
>&
a
)
   
{
       
if
(
a
.
size
()
<=
1
)
return
0
;
       
int
max
=
0
;
       
for
(
int
i
=
1
;
i
<
a
.
size
();
i
++)
       
{
           
if
(
a
[
i
]>
a
[
i
-
1
])
max
+=
a
[
i
]-
a
[
i
-
1
];
       
}
       
return
max
;
       
   
}
};
 
123
.
 
Best Time to Buy and Sell Stock III (hard题)
Say you have an array for which the
 
i
th
 
element is the price of a given stock on day
 
i
.
Design an algorithm to find the maximum profit. You may complete at most
 
two
 
transactions.
Note: 
You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again).
Example 1:
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.
Example 2:
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.
Example 3:
Input:
[7,6,4,3,1]
Output:
0
Explanation:
In this case, no transaction is done, i.e. max profit = 0.
 
//
问题:股票买卖问题
3
(最多交易两次,这里一次交易指买
+
卖)
/*
方法:
4
标记(变量)法
*
  buy1 -
第一次买入后的收益,买入后收益为负数
  sell1 -
第一次卖出时的收益
  buy2 -
第二次买入后的收益
  sell2 -
第二次卖出后的收益
 
保证操作的收益最大(对于
buy
后的收益,实质是为了最小化成本)
 
(局部最优,带来全局最优,贪心法)
 
*/
#include <climits>
#include <algorithm>
class
Solution
{
public
:
   
int
maxProfit
(
vector
<
int
>&
a
)
   
{
       
int
buy1
=
INT_MIN
,
sell1
=
0
,
buy2
=
INT_MIN
,
sell2
=
0
;
       
for
(
int
ai
:
a
)
       
{
            buy1
=
max
(
buy1
,
-
ai
);
//
当选择前一个数时表示不进行交易,选择后一个数时进行买入,花费
ai
的成本,收益变为
-ai
            sell1
=
max
(
sell1
,
buy1
+
ai
);
            buy2
=
max
(
buy2
,
sell1
-
ai
);
            sell2
=
max
(
sell2
,
buy2
+
ai
);
           
//
如何保证每次只进行一个操作?
(buy1
sell1
不会同时操作,
buy2
sell2
不会同时操作
)
       
}
       
return
sell2
;
   
}
};
 
188
.
 
Best Time to Buy and Sell Stock IV (hard)
Say you have an array for which the
 
i
th
 
element is the price of a given stock on day
 
i
.
Design an algorithm to find the maximum profit. You may complete at most
 
k
 
transactions.
Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
Example 1:
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.
Example 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.
 
//
问题:股票买卖问题
4
(最多交易
k
次,这里一次交易指买
+
卖)
/*
*
方法:
DP
(
找递推公式
)
*
解释:与问题
3
的方法类似,每次操作与上次操作有关,确保每次操作的收益最大
 
如果
k >= len/2
,则和问题
1
一样,相当于买卖次数没有限制,直接用求全局最优即可
 
buy[i][j-1]表示对于j-1天,第i次买入后的最大收益,为了节省空间可写成单变量buy
sell[i][j] 表示对于j天,第i次卖出后的最大收益
递推公式:
buy = max( buy,  sell[i-1][j-1] - a[j-1] )
 //j-1天,第i次买入(承接j-1天,第i-1次卖出,sell[i-1][j-1]),对应第j-1天不买,或者买(则减去a[j-1])
sell[i][j] = max( sell[i][j-1],  buy + a[j] ) 
//j天,第i次卖出(承接j-1天第i次买入),对应第j天不卖(
sell[i][j-1]
)或者卖(则加上a[j])
 
 
 
了解即可!!
*/
#include <algorithm>
#include <climits>
class
Solution
{
public
:
   
int
maxProfit
(
int
k
,
vector
<
int
>&
a
)
   
{
       
if
(
a
.
empty
())
return
0
;
       
       
int
n
=
a
.
size
();
       
if
(
k
>=
n
/
2
)
//
如果买卖次数没有限制,则直接全局处理,变为问题二
       
{
           
int
maxprofit
=
0
;
           
for
(
int
i
=
1
;
i
<
n
;
i
++)
           
{
               
if
(
a
[
i
]
>
a
[
i
-
1
])
maxprofit
+=
a
[
i
]
-
a
[
i
-
1
];
           
}
           
return
maxprofit
;
       
}
       
        vector
<
vector
<
int
>>
sell
(
k
+
1
,
vector
<
int
>(
n
));
//交易次数多开辟一段空间,以提供初值,以及索引方便
 
       
for
(
int
i
=
1
;
i
<=
k
;
i
++)
//遍历交易次数,i=1~k
       
{
           
           
int
buy
=
sell
[
i
-
1
][
0
]-
a
[
0
];
//
初始化
           
for
(
int
j
=
1
;
j
<
n
;
j
++)
//遍历天数,j=1~n-1(天数从0开始,式中有j-1)
           
{
               
//buy
a[0]
开始,
sell
a[1]
开始,错开以避免重复交易
                
buy 
= 
max
(
buy
, 
sell
[
i
-
1
][
j-1
]-
a
[
j-1
]); 
//j-1天
i
次买入后的收益,(注意这里与sell[i-1][j-1]相比较,有承接性,以避免多次交易重复买卖)
                sell
[
i
][
j
]
=
max
(
sell
[
i
][
j
-
1
],
buy
+
a
[
j
]);
//j天
i
次卖出之后的收益
           
}
       
}
       
return
sell
[
k
][
n
-
1
];
//
返回第
k
次卖出后的收益
       
   
}
};
 
 
309
.
 
Best Time to Buy and Sell Stock with Cooldown
Say you have an array for which the
 
i
th
 
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:
Input:
[1,2,3,0,2]
Output:
3
Explanation:
transactions = [buy, sell, cooldown, buy, sell]

 
/*
了解即可
 
问题:买卖多次,但是有冷冻期,卖出股票后要间隔一天才能再次买入
方法:动态规划
buy[i]
表示在第
i
天之前最后一个操作是买,此时的最大收益
sell[i]
表示在第
i
天之前最后一个操作是卖,此时的最大收益
则有递推式:
buy[i]  = max(sell[i-2] - price, buy[i-1]) i
天,买入收益,第
i
天买(由于存在一天的冷冻期,承接
i-2
天的卖出收益
sell[i-2]
)或者不买(承接
buy[i-1]
sell[i] = max(buy[i-1] + price, sell[i-1]) i
天,卖出收益,第
i
天卖(承接
buy[i-1
,
或者不卖(承接
sell[i-1]
由于
i
只依赖于
i-1
i-2
,所以我们可以在
O(1)
的空间复杂度完成算法
*/
class
Solution
{
public
:
   
int
maxProfit
(
vector
<
int
>&
prices
)
   
{
       
int
buy
=
INT_MIN
,
pre_buy
=
0
,
sell
=
0
,
pre_sell
=
0
;
       
for
(
int
price
:
prices
)
       
{
            pre_buy
=
buy
;
            buy
=
max
(
pre_sell
-
price
,
pre_buy
);
//i
天的买入收益与
i-2
天的卖出收益有关
            pre_sell
=
sell
;
            sell
=
max
(
pre_buy
+
price
,
pre_sell
); //i天的卖出收益与i-1天的买入收益有关
       
}
       
return
sell
;
   
}
};
 
 
 
 
 

 

转载于:https://www.cnblogs.com/wikiwen/p/10229377.html

你可能感兴趣的文章
二进制文件的查看和编辑
查看>>
C# Async与Await的使用
查看>>
Mysql性能调优
查看>>
iOS基础-UIKit框架-多控制器管理-实例:qq界面框架
查看>>
javascript学习---BOM
查看>>
IOS-每个程序员的编程之路上都应该看这11本书
查看>>
自定义tabbar(纯代码)
查看>>
extjs fieldset 和 radio
查看>>
小程序底部导航栏
查看>>
Codeforces Gym101505G:Orchard Division(扫描线+线段树第k大)
查看>>
ibatis学习笔记
查看>>
18-ES6(1)
查看>>
poj1611 简单并查集
查看>>
tensorflow实现迁移学习
查看>>
Ubuntu 14.04下安装CUDA8.0
查看>>
跨平台开发 -- C# 使用 C/C++ 生成的动态链接库
查看>>
关于Redis处理高并发
查看>>
C# BS消息推送 SignalR介绍(一)
查看>>
asp.net core 系列 16 Web主机 IWebHostBuilder
查看>>
WPF星空效果
查看>>