股票最佳买卖时机动态规划_买卖股票的最佳时机--动态规划

本人已迁移博客至掘进,以后会在掘进平台更新最新的文章也会有更多的干货,欢迎大家关注!!!https://juejin.im/user/588993965333309

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。

注意你不能在买入股票前卖出股票。

示例 1:

输入: [7,1,5,3,6,4]

输出:5解释: 在第2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5。

注意利润不能是7-1 = 6, 因为卖出价格需要大于买入价格。

示例2:

输入: [7,6,4,3,1]

输出:0解释: 在这种情况下, 没有交易完成, 所以最大利润为0。

解法一: 暴力解决法

算法思想:

我们需要找出给定数组中两个数字之间的最大差值(即,最大利润)。此外,第二个数字(卖出价格)必须大于第一个数字(买入价格)。

对于每组 i 和 j (j > i)我们需要找出max(prices[j] - prices[i])

代码如下:

func maxProfit(_ prices: [Int]) ->Int {

guard prices.count> 0 else {return 0}

var maxProfit: Int= 0

for i in 0..

maxProfit= max(maxProfit, prices[j] -prices[i])

}

}returnmaxProfit

}

解法二:动态规划

算法思想:

动态规划的3个步骤:

设定状态

推导方程

起始值和输出

这里状态的设置得稍微想一想,数组的问题一般我们得固定其中一个变量。这道题有两个变量,一个是“买入”,另一个是“卖出”,这里我们固定“卖出”变量,“买入”变量一定在它之前。

因此状态dp[i]表示:在索引为 i 的这一天,用户所能获得的最大利润。

下面思考状态转移,我们就要想dp [i] 的从前面的状态值转移过来,但是我们就会发现新的问题dp[i - 1]、dp[i - 2]、……、dp[0],状态转移无从下手。这里就说明:状态还不够,得把“买入”和“卖出”操作加入到状态的设置中。

于是下面修改状态的定义:

dp[i][0]表示:在索引为 i 的这一天,用户手上不持股所能获得的最大利润;

1、 0 一般表示没有,在索引为 i 的这一天,手上没有股票,语义上也是清晰的,下面对状态 1的理解也是一样;2、 “用户手上不持股”不代表用户一定在索引为 i 的这一天把股票抛售了;3、 在索引为 i 的这一天具体应该这样理解:从索引为 0 的天数开始,到索引为 i 的这一天,因此,这个状态的设置具有“前缀”的意味,因此输出是 dp[len - 1][0],不可能是 dp[len - 1][1],在只发生一次交易的情况下,持有这支股票一定不能使我们获得最大利润。

状态dp[i][1]表示:在索引为 i 的这一天,用户手上持股所能获得最大的利润。

下面考虑状态转移方程:

dp[i][0] 可以由谁转移过来?

dp[i - 1][0] :今天不持股,假设我今天什么都不操作,当然可以从昨天不持股转移过来,这一点是显然的

dp[i - 1][1] + prices[i]:昨天持股,就在索引为 i 的这一天,我卖出了股票,状态由 1 变成了 0,此时获得利润,因此加上这一天的股价。

综上:dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]);

2. dp[i][1] 可以由谁转移过来?

dp[i - 1][1] :今天持股,假设我今天什么都不操作,当然可以从昨天持股转移过来,这一点是显然的;

-prices[i]:**请注意:**状态 1 不能由状态 0 来,因为事实上,状态 0 特指:“卖出股票以后不持有股票的状态”,请注意这个状态和“没有进行过任何一次交易的不持有股票的状态”的区别。

因此,-prices[i] 就表示,在索引为 i 的这一天,执行买入操作得到的收益,再次强调:因为题目只允许一次交易,因此不能加上 dp[i - 1][0]。

综上:dp[i][1] = max(dp[i - 1][1], -prices[i]);

在新修改的定义中,我们已经分析出了输出dp[len - 1][0]

public int maxProfit(int[] prices) {int len =prices.length;if (len < 2) {return 0;

}//0:用户手上不持股所能获得的最大利润,特指卖出股票以后的不持股,非指没有进行过任何交易的不持股//1:用户手上持股所能获得的最大利润//注意:因为题目限制只能交易一次,因此状态只可能从 1 到 0,不可能从 0 到 1//状态转移方程://dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i])//dp[i][1] = max(dp[i - 1][1], -prices[i])

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], -prices[i]);

}return dp[len - 1][0];

}

以上就是股票最大收益算法,希望对大家有所帮助!!!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值