当前位置: 首页 > article >正文

力扣121-买卖股票的最佳时机(Java详细题解)

题目链接:121. 买卖股票的最佳时机 - 力扣(LeetCode)

前情提要:

因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。

dp五部曲。

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

2.确定递推公式。

3.dp初始化。

4.确定dp的遍历顺序。

5.如果没有ac打印dp数组 利于debug。

每一个dp题目如果都用这五步分析清楚,那么这道题就能解出来了。

题目思路:

本题是买卖股票系列的一个开始,所以本题很重要,大家要重点掌握。

首先看看题目描述,本题要求我们买卖股票后的最大利润,买卖股票只能进行一次。

那我们就得考虑在什么时候买股票和什么时候卖股票对吧。

其实什么时候买什么时候卖是不好推出我们的所有状态的。

我们这里主要是将状态分为持股不持股俩个状态。

注意这里说的是“持有”,“持有”不代表就是当天“买入”!也有可能是昨天就买入了,今天保持持有的状态

持股的意思是我当前持有股票的状态,我可能是当天买的也可能之前就持股了。

不持股就是我当前不持有股票的状态,我可能是当天卖的也可能之前就是不持股。这样我们就可以把整个dp数组给推出来。

接下来我们用dp五部曲系统分析一下。

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

dp[i] [0]指的就是下标为i天持股手上的最大现金。

dp[i] [1]指的就是下标为i天不持股手上的最大现金。

可能有人会疑问,那我第一次买入股票那现金不是负的嘛。

确实是负的,不过我们求的是最大的负的,也就是实数中最小的数。其实就是得到最小买入股票的价格。

2.确定递推公式。

下标为i天持股手上的最大现金的状态可以由俩个状态推出。

我当天持股可能我前一天也是持股的状态,也可能是我当天买入股票的状态。

dp[i] [0] = Math.max(dp[i - 1] [0],-prices[i]);

因为本题只能买卖一次,所以第一买肯定是负数 也就是 0 - prices[i];

下标为i天不持股手上的最大现金的状态也可以由俩个状态推出。

我当天不持股可能我前一天也是不持股的状态,也可能是我当天卖出股票的状态。

我当天卖出,那我的前一天肯定是持股的状态,那我就将前一天持股手上的最大现金加上我当天卖出的股票最大现金,也就是我的最大不持股的现金(所得的利润)。

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

3.dp初始化。

该题可以从dp定义和递推公式来进行初始化。

可以看出dp[i]是由dp[i - 1]推出,所以需要前一个状态,那么我们所有状态的起始状态就是dp[0]

所以我们对dp[0]进行初始化。

dp[0] [0]是表示我i下标为0持股的状态,那肯定是当天买入股票的状态,因为他前面没有状态了,所以dp[0] [0] = -prices[0]

dp[0] [1]是表示我i下标为0不持股的状态,那就是我当天买当天买了,那手上的最大现金就为0了。所以dp[0] [1] = 0;

4.确定dp的遍历顺序。

可以看出dp[i]是由dp[i - 1]推出,所以需要前一个状态,那么我们的遍历顺序肯定是从前往后来推。

5.如果没有ac打印dp数组 利于debug。

在这里插入图片描述

最终代码:

class Solution {
    public int maxProfit(int[] prices) {
        //定义dp数组 表示第i天持股的最大现金(其实就是得到最小买入股票的价格,因为买入股票剩下的现金都为负数,在负数中最大就是实数中最小的数) 和 第i天不持股的最大现金(其实就是得到最大买出股票的价格)
        //dp的定义
        int [][] dp = new int [prices.length + 1][2];
        //dp初始化
        dp[0][0] = -prices[0];
        dp[0][1] = 0;
        //dp遍历顺序
        for(int i = 1;i < prices.length;i ++){
            //dp递推公式
            dp[i][0] = Math.max(dp[i - 1][0],-prices[i]);
            dp[i][1] = Math.max(dp[i - 1][1],dp[i - 1][0] + prices[i]);
        }
        //最后一天的不持股(没有股票,可能在最后一天之前就已经卖了)得到的现金因为递推公式,被前面最大的卖出股票的价格所覆盖了,所以获得的最大利润就为dp[prices.length - 1][1]
        //在本题持股的最大现金一定为负数,所以得的最大值就是不持股的最大现金
        return dp[prices.length - 1][1];
    }
}

这一篇博客就到这了,如果你有什么疑问和想法可以打在评论区,或者私信我。

我很乐意为你解答。那么我们下篇再见!


http://www.kler.cn/a/309122.html

相关文章:

  • Springboot整合Prometheus+grafana实现系统监控
  • 谷歌浏览器的自动翻译功能如何开启
  • Prompt 工程
  • 第二天python笔记
  • Linux——基础指令2 + 权限
  • 电脑提示xinput1_3.dll丢失怎么办?游戏DLL修复方法详解
  • Encountered 31 files that should have been pointers, but weren‘t:(已解决,无废话)
  • System.out源码解读——err 和 out 一起用导致的顺序异常Bug
  • 论文翻译:USENIX-2021 Extracting Training Data from Large Language Models
  • 网络设备登录——《路由与交换技术》实验报告
  • 养宠浮毛严重怎么清理?希喂、范罗士、IAM宠物空气净化器真实测评
  • C++:初始化列表
  • 在线包装盒型生成工具,各种异型包装盒型,PDF导出方便
  • 【蜡笔小新专享】安装虚拟机、PHP、DVWA
  • Linux容器化管理——Docker常见命令总结
  • Apache Pulsar 与 Kafka Streams
  • React实现类似Vue的路由监听Hook
  • 在新电脑上将文件推送到已有的 Git 仓库
  • 【编程基础知识】Java命名规范及最佳实践
  • 孙怡带你深度学习(2)--PyTorch框架认识
  • Unity实战案例全解析:PVZ 植物卡片状态分析
  • 【乐企】基础版接口代码实现
  • Spring Boot校园管理系统:技术选型与架构设计
  • Java | Leetcode Java题解之第405题数字转换为十六进制数
  • TS React 项目中使用TypeScript
  • 【Java】synchronized 基础线程安全