- 股票的最大价值I (leetcode 121)
- 题目:假设把某股票的价格按照时间先后顺序存储再数组中,请问买卖该股票一次可能获得的最大利润是多少?例如,一只股票在某些时间节点的价格为{9,11,8,5,7,12,16,14}。如果5买入,16迈出,则利润为11.
- 思路:
- 定义一个函数diff(i) 表示为卖出价格为数组下标为i的元素时获得的最大利润。显然只要找到前i-1个数中最小的元素,就能算出当前的最大利润。
- 代码:
class Solution {
public int maxProfit(int[] prices) {
if(prices==null||prices.length<2){
return 0;
}
int min = prices[0];
int curMaxPro = 0;
for(int i=1;i<prices.length;i++){
if(curMaxPro<prices[i]-min){
curMaxPro = prices[i]-min;
}
if(prices[i]<min){
min = prices[i];
}
}
return curMaxPro;
}
}
- 股票的最大值II (leetcode 122)
- 题目:假设有一个数组,它的第i个元素是一个给定的股票在第i天的价格。设计一个算法来找到最大的利润。你可以完成尽可能多的交易(多次买卖股票)。然而,你不能同时参与多个交易(你必须在再次购买前出售股票)。
- 思路:
- 本题由于是可以操作任意次数,只为获得最大收益,而且对于一个上升子序列,比如:[5, 1, 2, 3, 4]中的1, 2, 3, 4序列来说,对于两种操作方案:1 在1买入,4卖出 2 在1买入,2卖出同时买入,3卖出同时买入,4卖出 这两种操作下,收益是一样的。所以可以从头到尾扫描prices,如果price[i] – price[i-1]大于零则计入最后的收益中。即贪心法
- https://www.jianshu.com/p/34bbb0594bd9
- 代码:
class Solution {
public int maxProfit(int[] prices) {
if(prices==null||prices.length<2){
return 0;
}
int curMaxProf = 0;
for(int i=0;i<prices.length-1;i++){
if(prices[i+1]>prices[i]){
curMaxProf += prices[i+1]-prices[i];
}
}
return curMaxProf;
}
}
- 股票的最大值III(leetcode 123)
- 题目:有一个数组arr,其中第i 个元素是第i天给定股票的价格。设计算法以找到最大利润。最多可以完成两笔交易。
- 思路:
- 还是动态规划的思想。因为最多时两笔交易。也就是说有两种情况可能达到最大利润。一种是完成一笔交易达到最大利润,还有一种是完成二笔交易达到最大利润。对于第一种情况:直接基于(股票的最大价值题)。那么对于第二种情况:我们可以把数组差成两部分的思想来做。什么意思呢》比如第i天为分界点,那么我们把第0到第i天内进行第一笔交易,第i+1到第n-1天进行第二笔交易。(1<=i<=n-2)。基于上叙思想,我们可以写个状态转移方程。
- 第0到第i天内进行第一笔交易:pre[i] 表示前i天内,进行一次交易能达到的最大价值。转移点怎么写呢,可以类比0-1背包的思想。前i天内,在第i天卖出还是不在第i天卖出这个状态点写一个状态转移方程,不在第i天卖出:相当于pre[i-1];在第i天卖出:arr[i]-preMin(preMin指的前i-1天股票的最小值)
- 因此状态转移方程为:pre[i] = max(pre[i-1],arr[i]-preMin);
- 同理;第i+1到第n-1天进行第二笔交易:back[i]表示第i到n-1天内,进行一次交易能达到的最大价值。转移点怎么写呢,同样类比0-1背包的思想。第i到n-1天内,在第i天买入还是不在第i天买入这个状态点写一个状态转移方程,不在第i天买入:相当于back[i+1];在第i天买入:backMax-arr[i](backMax指的第i+1天到第n-1天股票的最大值)
- 因此状态转移方程为:back[i] = max(back[i-1],backMax-arr[i]);
- 那么得出两个状态数组,我们可以利用 max(pre[i]+back[i+1])得到两笔交易的最大价值 (0=<i<len-1)pre[len-1] 为进行一笔交易的最大值
- 代码:(java 时间O(N) 空间O(N))
class Solution {
public int maxProfit(int[] prices) {
if(prices==null||prices.length<=0) return 0;
int len = prices.length;
int pre[] = new int[len];//表示前i天内,进行一次交易能达到的最大价值
int preMin = prices[0];
int curMax = 0;
for(int i=1;i<len;i++){
if(curMax<prices[i]-preMin){
curMax = prices[i]-preMin;
}
pre[i] = Math.max(pre[i-1],curMax); //curMax指前i天 进行一次交易且第i天卖出所达到的最大值
preMin = Math.min(preMin,prices[i]);
}
int back[] = new int[len]; //表示第i天到第n-1天内,进行依次交易能达到的最大价值
int bacMax = prices[len-1];
curMax = 0;
for(int j=len-2;j>=0;j--){
if(curMax<bacMax-prices[j]){
curMax = bacMax-prices[j];
}
back[j] = Math.max(back[j+1],curMax);
bacMax = Math.max(bacMax,prices[j]);
}
int res = 0;
for(int i=0;i<len;i++){
if(i!=len-1){
res = Math.max(res,pre[i]+back[i+1]);
}else{
res = Math.max(res,pre[i]);
}
}
return res;
}
}
- Best Time to Buy and Sell Stock with Transaction Fee (leetcode 714)
- 题目:一个整数数组prices,其中prices[i]表示一天给定股票的价格;fee表示交易费用的非负整数。根据需要完成尽可能多的交易,但是需要为每笔交易支付交易费用。一次不能购买超过1股的股票(即必须在再次购买之前卖出股票。)
- 思路:
- 动态规划
- 动态转移点:手上有没有股票 进行DP
- 对于第i天的最大收益,应分成两种情况,一是该天结束后手里没有stock,可能是保持前一天的状态也可能是今天卖出了,此时令收益为cash;二是该天结束后手中有一个stock,可能是保持前一天的状态,也可能是今天买入了,用hold表示。由于第i天的情况只和i-1天有关,所以用两个变量cash和hold就可以,不需要用数组
- 代码:
class Solution {
public int maxProfit(int[] prices, int fee) {
if(prices==null||prices.length<=1) return 0;
int buy = -prices[0];
int cash = 0;
for(int i=1;i<prices.length;i++){
cash = Math.max(cash,buy+prices[i]-fee);
buy = Math.max(buy,cash-prices[i]);
}
return cash;
}
}
- 贪心算法:
- 贪心选择的关键是找到一个最大后是不是能够卖掉stock,重新开始寻找买入机会。比如序列1 3 2 8,如果发现2小于3就完成交易买1卖3,此时由于fee=2,(3-1-fee)+(8-2-fee)<(8-1-fee),所以说明卖早了,令max是当前最大price,当(max-price[i]>=fee)时可以在max处卖出,且不会存在卖早的情况,再从i开始重新寻找买入机会。
- 代码:
class Solution {
public int maxProfit(int[] prices, int fee) {
if(prices==null||prices.length<=1) return 0;
int profit=0;
int curProfit=0;
int minP=prices[0];
int maxP=prices[0];
int i;
for(i=1;i<prices.length;i++){
minP=Math.min(minP,prices[i]);
maxP=Math.max(maxP,prices[i]);
curProfit=Math.max(curProfit,prices[i]-minP-fee);
if((maxP-prices[i])>=fee){
profit+=curProfit;
curProfit=0;
minP=prices[i];
maxP=prices[i];
}
}
return profit+curProfit;
}
}
- 动态规划
Best Time to Buy and Sell Stock(股票的价值系列 整理总结)
最新推荐文章于 2020-03-09 12:24:36 发布