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

2020-03-11 18:19:00

问题描述:

给出一个股票n天的价格,每天最多只能进行一次交易,可以选择买入一支股票或卖出一支股票或放弃交易,输出能够达到的最大利润值

样例

样例 1:

给出 `a = [1,2,10,9]`, 返回 `16`

输入:

[1,2,10,9]

输出:

16

解释:

你可以在第一天和第二天买入股票,第三天和第四天卖出

利润:-1-2+10+9 = 16

样例 2:

给出 `a = [9,5,9,10,5]`, 返回 `5`

输入:

[9,5,9,10,5]

输出:

5

解释:

你可以在第2天买入,第4天卖出

利润:-5 + 10 = 5

注意事项

1 ≤ n ≤ 10000

问题求解:

之前Stock Problems里有遇到过k交易,每次手里至多有1个股票的问题;这里是一个扩展题,交易数量不限,而且手里的股票数量也不限。

网络上有人发了dfs的解,自己也尝试过使用dfs来做,但是是会TLE的,使用dfs不做剪枝操作理论的时间复杂度是指数级别的。

正确的解法是使用dp。

dp[i][j] : 前i天结束手里有j个股票所能达到的最大值

对于dp[i][j]就有三种策略,不做交易dp[i - 1][j],买入dp[i - 1][j - 1] - prices[i - 1],卖出dp[i - 1][j + 1] + prices[i - 1]。

边界条件再完善一下就可以了。

本题直接开dp[n + 1][n + 1]会MLE,需要使用滚动数组来降低空间复杂度才能AC。另外,感觉题目的test case比较水,没有达到10000的量级,上述的解的时间复杂度约为O(n ^ 2),理论上是过不了大数据的。尝试提交了一下,还是AC了。

时间复杂度 :O(n ^ 2)。

public int getAns(int[] a) {

int n = a.length;

int[] dp = new int[n + 1];

int[] presum = new int[n];

presum[0] = a[0];

for (int i = 1; i < n; i++) presum[i] = presum[i - 1] + a[i];

dp[0] = 0;

for (int i = 1; i <= n; i++) dp[i] = Integer.MIN_VALUE;

for (int i = 1; i <= n; i++) {

int[] prev = Arrays.copyOf(dp, n);

dp[0] = Math.max(prev[0], prev[1] + a[i - 1]);

dp[i] = -presum[i - 1];

dp[i - 1] = Math.max(dp[i - 1], i >= 2 ? prev[i - 2] - a[i - 1] : Integer.MIN_VALUE);

for (int j = 1; j <= i - 2; j++) {

dp[j] = Math.max(Math.max(prev[j], prev[j - 1] - a[i - 1]), prev[j + 1] + a[i - 1]);

}

}

return dp[0];

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值