【LeetCode】【Java】【买卖股票的最佳时机】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z3bcEwYl-1666752551811)(file://D:\资源\学习工作\lnnau\typora笔记\Mark Text\算法比赛刷题\LeetCode\初级算法\assets\买卖股票的最佳时机\2022-10-26-09-27-44-image.png?msec=1666750262774)]

转换思维:

题目说使得卖出股票的利益最大,那么也可以理解成使得自己的现金最大(经过买入和卖出后),那么是不是应该在最便宜的时候买入,最贵的时候卖出,这样就把问题转换为求买入股票后自己的剩余现金最大卖出后自己的现金依然最大的问题了。

1.确定dp数组和下标含义

dp[i][0]:第i天所持有股票时,你的现金数

dp[i][1]:第i天不持有股票时,你的现金数

2.确定递推公式

第i天持有股票dp[i][0],可以由两个状态推出

  1. dp[i-1][0]:第i-1天就持有股票,那么第i天的现金就为第i-1天的现金数

  2. -price[i]:第i-1天不持有现金,那么第i天的现金就为第i的买股票后剩余的现金数

目的是使得买入后自己剩余现金最大,所以就求两个状态的最大值

dp[i][0] = max(dp[i-1][0],-price[i])

第i天不持有股票dp[i][1],可以由两个状态推出

  1. dp[i-1][1]:第i-1天不持有股票,那么第i天的现金就为昨天的现金数

  2. price[i]+dp[i-1][0]:第i天卖出股票,那么第i天的现金就为卖出股票的现金加上i-1天持有股票的现金数

dp[i][1] = max(dp[i-1][1],prices[i] + dp[i-1][0])

3.dp数组初始化

由于dp[i-1][0]和dp[i-1][1]都是从第一列推出的,所以初始化dp[0][0]和dp[0][1]即可

dp[0][0]:第0天持有股票的现金,由于这是第一天,所以该天的现金就为买入股票后剩余现金 -price[0]

dp[0][1]:第0天不持有股票的现金,由于第一天不持有的话,那么该天的现金就为现金起始值,就是0

4.确定递推顺序

从递推公式可以看出dp[i]都是有dp[i - 1]推导出来的,那么⼀定是从前向后遍历

5.举例推导dp数组

用示例1,输⼊:[7,1,5,3,6,4]为例,dp数组状态如下:

dp[i][0]dp[i][1]
0-70
1-10
2-14
3-14
4-15
5-15

可以看到,dp[i][1]为最终结果,含义就是第5天不持有股票时的现金数

案例2的状态

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xYNNNvIq-1666752551813)(file://D:\资源\学习工作\lnnau\typora笔记\Mark Text\算法比赛刷题\LeetCode\初级算法\assets\买卖股票的最佳时机\2022-10-26-10-36-51-image.png?msec=1666751812000)]

代码

class Solution {
    public int maxProfit(int[] prices) {
        int len = prices.length;
        //定义dp数组
        int[][] dp = new int[len][2];
        //初始化dp数组
        dp[0][0] = -prices[0];
        dp[0][1] = 0;
        for (int i=1; i<len; i++) {
            //第i天持有股票时的现金数 i-1天时持有或者i天买入
            dp[i][0] = Math.max(dp[i-1][0],-prices[i]);
            //第i天不持有股票的现金数
            dp[i][1] = Math.max(dp[i-1][1],prices[i] + dp[i-1][0]);
        }
        return dp[len-1][1];
    }
}
posted @ 2022-10-26 10:50  Lnnau  阅读(17)  评论(0)    收藏  举报  来源