LeetCode-题目整理【3】:买卖股票的最佳时机

买卖股票的最佳时机 都是求最大利润,但是在没有限制,如121和122,动态规划稍微复杂一些,建议不用,到最后两道难题,题目有限制,使用动态规划通过求解子问题的最优解来逐步求解原问题的最优解。

  1. 买卖股票的最佳时机 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
    返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
    示例 1:
    输入:[7,1,5,3,6,4]
    输出:5
    解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
    注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
    示例 2:
    输入:prices = [7,6,4,3,1]
    输出:0
    解释:在这种情况下, 没有交易完成, 所以最大利润为 0。
func maxProfit(prices []int) int {minPrice := prices[0]maxProfit := 0for i := 1; i < len(prices); i++ {if prices[i] < minPrice {minPrice = prices[i]} else if prices[i] - minPrice > maxProfit {maxProfit = prices[i] - minPrice}}return maxProfit
}
//动态规划解答func maxProfit(prices []int) int {if len(prices) == 0 {return 0}n := len(prices)dp := make([]int, n)dp[0] = 0minPrice := prices[0]for i := 1; i < n; i++ {minPrice = min(minPrice, prices[i])dp[i] = max(dp[i-1], prices[i]-minPrice)}return dp[n-1]
}func min(a, b int) int {if a < b {return a}return b
}func max(a, b int) int {if a > b {return a}return b
}// 使用动态规划来解决这个问题,可以通过定义状态和状态转移方程来求解最大利润。// 具体步骤如下:// 定义状态:使用一个一维数组 dp 来表示在第 i 天的最大利润,dp[i] 表示第 i 天卖出股票所能获取的最大利润。
// 初始化状态:dp[0] 初始化为 0。
// 状态转移方程:对于第 i 天,可以选择卖出股票或者不卖出股票。如果选择卖出股票,则最大利润为 prices[i] - minPrice,其中 minPrice 表示前 i 天的最低价格。如果选择不卖出股票,则最大利润为前一天的最大利润 dp[i-1]。因此,状态转移方程为 dp[i] = max(dp[i-1], prices[i] - minPrice)。
// 更新最低价格:在更新状态之前,需要将当前价格 prices[i] 和之前的最低价格 minPrice 进行比较,更新最低价格为较小的那个。
// 遍历结束后,返回 dp[n-1],其中 n 表示数组 prices 的长度。
  1. 买卖股票的最佳时机 II
    给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。
    在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。
    返回 你能获得的 最大 利润 。
    示例 1:
    输入:prices = [7,1,5,3,6,4]
    输出:7
    解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
    随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3 。
    总利润为 4 + 3 = 7 。
    示例 2:
    输入:prices = [1,2,3,4,5]
    输出:4
    解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
    总利润为 4 。
    示例 3:
    输入:prices = [7,6,4,3,1]
    输出:0
    解释:在这种情况下, 交易无法获得正利润,所以不参与交易可以获得最大利润,最大利润为 0 。
func maxProfit(prices []int) int {if len(prices) <= 1 {return 0}maxProfit := 0for i := 1; i < len(prices); i++ {if prices[i] > prices[i-1] {maxProfit += prices[i] - prices[i-1]}}return maxProfit
}// 使用了贪心算法来解决问题,通过每次在价格上升时买入股票,价格下降时卖出股票,从而获取最大利润。// 具体步骤如下:// 初始化最大利润为 0。
// 遍历股票价格数组,从第 2 天开始。
// 如果当天的股票价格比前一天高,则将差值加入最大利润中。
// 遍历结束后,返回最大利润。
// 这种方法的思路是,当股票价格上涨时,我们可以在价格上涨期间多次买入和卖出,从而获取更多的利润。而当股票价格下跌时,我们不进行任何操作。
//动态规划func maxProfit(prices []int) int {if len(prices) == 0 {return 0}n := len(prices)buy := make([]int, n)  // 当前持有股票的最大利润sell := make([]int, n) // 当前不持有股票的最大利润// 初始化第一天的情况buy[0] = -prices[0]sell[0] = 0for i := 1; i < n; i++ {// 当前持有股票的最大利润,要么继续保持前一天的状态,要么今天买入buy[i] = max(buy[i-1], sell[i-1]-prices[i])// 当前不持有股票的最大利润,要么继续保持前一天的状态,要么今天卖出sell[i] = max(sell[i-1], buy[i-1]+prices[i])}// 最终返回最后一天不持有股票的最大利润return sell[n-1]
}func max(a, b int) int {if a > b {return a}return b
}// 使用动态规划来解决。
// 具体步骤如下:// 定义状态:使用两个一维数组 buy 和 sell 来分别表示在第 i 天持有股票和不持有股票时的最大利润。buy[i] 表示第 i 天持有股票时的最大利润,sell[i] 表示第 i 天不持有股票时的最大利润。
// 初始化状态:buy[0] 初始化为 -prices[0],表示第 0 天持有股票的最大利润;sell[0] 初始化为 0,表示第 0 天不持有股票的最大利润。
// 状态转移方程:对于第 i 天,如果选择持有股票,则最大利润为前一天持有股票的最大利润 buy[i-1] 或者前一天不持有股票的最大利润减去当天的股价 sell[i-1] - prices[i] 中的较大值;如果选择不持有股票,则最大利润为前一天不持有股票的最大利润 sell[i-1] 或者前一天持有股票的最大利润加上当天的股价 buy[i-1] + prices[i] 中的较大值。因此,状态转移方程为 buy[i] = max(buy[i-1], sell[i-1] - prices[i]),sell[i] = max(sell[i-1], buy[i-1] + prices[i])。
// 遍历数组结束后,返回 sell[n-1],其中 n 表示数组 prices 的长度。
  1. 买卖股票的最佳时机 III
    给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。
    设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。
    注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
    示例 1:
    输入:prices = [3,3,5,0,0,3,1,4]
    输出:6
    解释:在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3 。
    随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3 。
    示例 2:
    输入:prices = [1,2,3,4,5]
    输出:4
    解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
    注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。
    因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。
    示例 3:
    输入:prices = [7,6,4,3,1]
    输出:0
    解释:在这个情况下, 没有交易完成, 所以最大利润为 0。
    示例 4:
    输入:prices = [1]
    输出:0
//动态规划func maxProfit(prices []int) int {if len(prices) == 0 {return 0}buy1 := -prices[0]sell1 := 0buy2 := -prices[0]sell2 := 0for i := 1; i < len(prices); i++ {buy1 = max(buy1, -prices[i])sell1 = max(sell1, buy1+prices[i])buy2 = max(buy2, sell1-prices[i])sell2 = max(sell2, buy2+prices[i])}return sell2
}func max(a, b int) int {if a > b {return a}return b
}// 可以使用动态规划来解决。// 具体步骤如下:// 定义状态:使用四个变量 buy1、sell1、buy2、sell2 来分别表示第一次买入、第一次卖出、第二次买入、第二次卖出时的最大利润。
// 初始化状态:buy1 初始化为 -prices[0],表示第一次买入的最大利润;sell1、buy2、sell2 初始化为 0。
// 状态转移方程:对于第 i 天,我们可以选择买入第一次、卖出第一次、买入第二次、卖出第二次或者不进行任何操作。因此,状态转移方程为:
// buy1 = max(buy1, -prices[i]),第一次买入的最大利润为前一天买入的最大利润 buy1 或者今天买入的价格 -prices[i] 中的较大值。
// sell1 = max(sell1, buy1 + prices[i]),第一次卖出的最大利润为前一天卖出的最大利润 sell1 或者今天卖出的价格加上第一次买入的最大利润 buy1 + prices[i] 中的较大值。
// buy2 = max(buy2, sell1 - prices[i]),第二次买入的最大利润为前一天买入的最大利润 buy2 或者今天买入的价格 -prices[i] 加上第一次卖出的最大利润 sell1 中的较大值。
// sell2 = max(sell2, buy2 + prices[i]),第二次卖出的最大利润为前一天卖出的最大利润 sell2 或者今天卖出的价格加上第二次买入的最大利润 buy2 + prices[i] 中的较大值。
// 遍历结束后,返回 sell2,即最大利润。
  1. 买卖股票的最佳时机 IV
    给你一个整数数组 prices 和一个整数 k ,其中 prices[i] 是某支给定的股票在第 i 天的价格。
    设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。也就是说,你最多可以买 k 次,卖 k 次。
    注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
    示例 1:
    输入:k = 2, prices = [2,4,1]
    输出:2
    解释:在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。
    示例 2:
    输入:k = 2, prices = [3,2,6,5,0,3]
    输出:7
    解释:在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。
    随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 。
//动态规划func maxProfit(k int, prices []int) int {if k == 0 || len(prices) == 0 {return 0}// 定义了一个辅助函数 maxProfitUnlimited 来计算不限制交易次数时的最大利润。if k >= len(prices)/2 {return maxProfitUnlimited(prices)}dp := make([][]int, len(prices))for i := 0; i < len(prices); i++ {dp[i] = make([]int, k+1)}for j := 1; j <= k; j++ {buy := -prices[0]for i := 1; i < len(prices); i++ {dp[i][j] = max(dp[i-1][j], prices[i]+buy)buy = max(buy, dp[i-1][j-1]-prices[i])}}return dp[len(prices)-1][k]
}// 和122. 买卖股票的最佳时机 II 使用贪心解法一样
// 定义了一个辅助函数 maxProfitUnlimited 来计算不限制交易次数时的最大利润。
func maxProfitUnlimited(prices []int) int {profit := 0for i := 1; i < len(prices); i++ {if prices[i] > prices[i-1] {profit += prices[i] - prices[i-1]}}return profit
}func max(x, y int) int {if x > y {return x}return y
}// 可以使用动态规划来解决。
// 定义一个二维数组 dp,其中 dp[i][j] 表示在第 i 天进行了 j 笔交易的最大利润。
// 具体步骤如下:// 初始化 dp 为一个大小为 (len(prices), k+1) 的二维数组,所有元素初始化为 0。
// 对于每一天 i,对于每一笔交易次数 j:
// 如果 j = 0,表示没有交易,利润为 0。
// 如果 i = 0,表示第一天,利润为 0。
// 否则,根据以下两种情况来更新 dp[i][j]:
// 第一种情况是在第 i 天不进行交易,即 dp[i][j] = dp[i-1][j]。
// 第二种情况是在第 i 天进行交易,即在前 i-1 天进行了 j-1 笔交易,然后在第 i 天买入股票,再在第 i 天卖出股票,即 dp[i][j] = dp[i-1][j-1] + prices[i] - prices[i-1]。
// 返回 dp[len(prices)-1][k],即为最大利润。// 在这个解法中,首先判断特殊情况,如果 k = 0 或者 prices 数组为空,直接返回 0。
// 然后,初始化二维数组 dp,并且对于每一天和每一笔交易次数,根据上述的两种情况来更新 dp。
// 最后,返回 dp[len(prices)-1][k],即为最大利润。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/641789.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言之反汇编查看函数栈帧的创建与销毁

文章目录 一、 什么是函数栈帧&#xff1f;二、 理解函数栈帧能解决什么问题呢&#xff1f;三、 函数栈帧的创建和销毁解析3.1、什么是栈&#xff1f;3.2、认识相关寄存器和汇编指令3.2.1 相关寄存器3.2.2 相关汇编命令 3.3、 解析函数栈帧的创建和销毁3.3.1 预备知识3.3.2 代码…

AI对比:ChatGPT和文心一言的区别和差异

目录 一、ChatGPT和文心一言大模型的对比分析 1.1 二者训练的数据情况分析 1.2 训练大模型数据规模和参数对比 1.3 二者3.5版本大模型对比总结 二、ChatGPT和文心一言功能对比分析 2.1 二者产品提供的功能情况分析 2.2 测试一下各种功能的特性 2.2.1 文本创作能力 2.2…

婴儿洗衣机怎么选?热门品牌希亦、觉飞、由利详细测评

宝宝的衣物是不是要和大人的衣服分开洗呢&#xff1f;这是很多新手爸妈都会遇到的一个问题。有的人认为&#xff0c;宝宝的衣服要单独洗&#xff0c;以免被大人的衣服上的细菌污染&#xff1b;有的人认为&#xff0c;宝宝的衣服可以和大人的衣服一起洗&#xff0c;这样可以节省…

优先级队列(堆)

目录 1 概念 2 堆的概念 2.1小根堆 2.2大根堆 3堆的存储方式​​​​​​​ 4、堆的创建 4.1堆向下调整 5、时间复杂度 6、堆的插入&#xff08;向上调整&#xff09; 7、堆的删除 8、PriorityQueue的特性 9、堆排序 1 概念 我们知道的队列&#xff0c;队列是一…

leetcode---Z字形变换

题目&#xff1a; 将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。比如输入字符串为 "PAYPALISHIRING" 行数为 3 时&#xff0c;排列如下&#xff1a;之后&#xff0c;你的输出需要从左往右逐行读取&#xff0c;产生…

Nginx入门教程+案例

摘要&#xff1a;Nginx 是一款轻量级的 Web 服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器。本文将介绍 Nginx 的基本概念、安装方法、配置文件以及一些常见应用场景&#xff0c;并通过一个简单的案例展示 Nginx 的实际应用。 一、Nginx 基本概…

redis高可用之主从部署

文章目录 前言1. 同步以及命令传播1.1 同步1.2 命令传播 2. 解决从服务器断线重连2.1 解决方案 3. PSYNC命令4. 复制步骤1:设置主服务器的地址和端口步骤2:建立套接字连接 ——其实就是建立TCP连接步骤3:发送PING命令步骤4:身份验证步骤5:发送端口信息步骤6:同步步骤7:命令传播…

鸿蒙5.0发布时间已定!何处寻得移动开发加速器?

直接在百度上搜索「鸿蒙5.0发布时间」&#xff0c;出来的结果&#xff0c;那一个比一个焦虑~~ 百度的AI基于综合内容判断得出&#xff0c;鸿蒙5.0的发布时间在2023-04-17 百度知道推的答案是202年年4月中 但不管几月&#xff0c;“鸿蒙元年”似乎都是确定的&#xff0c;就是…

Linux切换jdk版本

参考文献&#xff1a;Linux 多个JDK的版本 脚本切换 - C小海 - 博客园 (cnblogs.com)

树莓派ubuntu:CSI接口摄像头安装驱动程序及测试

树莓派中使用OV系列摄像头&#xff0c;网上能搜到的文章资源太老了&#xff0c;文章中提到的摄像头配置选项在raspi-config中并不存在。本文重新测试整理树莓派摄像头的驱动安装、配置、测试流程说明。 libcamera 新版本中使用libcamera作为摄像头驱动程序。 libcamera是一个…

【计算机系统组成原理】操作系统处理器深入介绍

博主介绍&#xff1a;✌全网粉丝喜爱、前后端领域优质创作者、本质互联网精神、坚持优质作品共享、掘金/腾讯云/阿里云等平台优质作者、擅长前后端项目开发和毕业项目实战✌有需要可以联系作者我哦&#xff01; &#x1f345;附上相关C语言版源码讲解&#x1f345; &#x1f44…

ZYNQ-7020 集成了运行NI Linux Real‑Time的实时处理器,支持FPGA二次开发

模拟和数字I/O&#xff0c;667 MHz双核CPU&#xff0c;512 MB DRAM&#xff0c;512 MB存储容量&#xff0c;Zynq-7020 FPGA CompactRIO Single-Board控制器 sbRIO‑9637是一款嵌入式控制器&#xff0c;在单块印刷电路板(PCB)上集成了运行NI Linux Real‑Time的实时处理器、用户…

RK3568 移植Ubuntu

使用ubuntu-base构建根文件系统 1、到ubuntu官网获取 ubuntu-base-18.04.5-base-arm64.tar.gz Ubuntu Base 18.04.5 LTS (Bionic Beaver) 2、将获取的文件拷贝到ubuntu虚拟机,新建目录,并解压 mkdir ubuntu_rootfs sudo tar -xpf u

docker 脚本安装

docker 脚本安装 curl -fsSL https://get.docker.com -o get-docker.sh bash get-docker.sh启动 systemctl enable docker systemctl daemon-reload systemctl start docker systemctl status dockerdocker run hello-world参考 docker-install

解密高压开关柜内温度感知神器——无线测温传感器

具长期电网运行数据表明&#xff0c;电网电气设备故障大多是由于大电流运行、设备老化、绝缘水平下降等原因导致设备在高温条件下运行&#xff0c;从而引发燃烧&#xff0c;爆炸等严重事故。因此准确的掌握电气设备温度是预防此类问题的关键。 开关柜无源无线测温传感器采用CT取…

氢能源展-2024武汉国际燃料电池展8月14-16日

氢能源展-2024武汉国际燃料电池展8月14-16日 2024武汉国际氢能源及燃料电池产业博览会 2024 Wuhan International Hydrogen Energy and Fuel Cell Industry Expo 同期举办&#xff1a;2024世界汽车制造技术暨智能装备博览会 时间&#xff1a;2024.8.14-16 地点&#xff1a;…

virtualenv虚拟环境的安装使用教程

让我们先思考这样一种情景&#xff1a;我们用python来开发一个项目&#xff0c;那么这个项目肯定会依赖很多的第三方库&#xff0c;这些第三方的库通过pip安装到全局区当中&#xff0c;而对于不同的项目使用到的库可能都有所不同&#xff0c;但是这些项目的库都安装到全局区当中…

【JavaEE进阶】MyBatis⼊⻔

文章目录 &#x1f332;什么是MyBatis?&#x1f333;准备⼯作&#x1f6a9;创建⼯程&#x1f6a9;数据准备&#x1f6a9;配置数据库连接字符串&#x1f6a9; 在项⽬中,创建持久层接⼝UserInfoMapper &#x1f343;单元测试&#x1f6a9;使⽤Idea⾃动⽣成测试类 &#x1f340;打…

【C语言】(2)数据类型

在 C 语言中&#xff0c;数据类型定义了变量或函数能够接受的数据形式。它们决定了数据存储的空间大小和如何解释存储的位模式。C语言提供了多种基本数据类型&#xff0c;可分为以下几类&#xff1a; 基本类型&#xff1a; 算术类型&#xff0c;包括两种类型&#xff1a;整数类…

Datalog 否定逻辑规则

在编写Datalog程序中&#xff0c;常常需要使用到比较逻辑&#xff0c;我目前遇到了两种&#xff0c;记录如下&#xff1a; 对某个relation的否定 例如目前我有一个relation表示一个操作符是否是可交换的——canExchange(op : Oper)&#xff0c;我想对不可交换的操作符进行检查…