【121. 买卖股票的最佳时机】——贪心算法/动态规划
121. 买卖股票的最佳时机
一、题目难度
简单
三、题目描述
给定一个数组 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
。
五、提示
1 <= prices.length <= 105
0 <= prices[i] <= 104
六、贪心算法求解思路
(一)整体思路
我们的目标是通过一次买入和一次卖出操作来获取最大利润。贪心算法的思路就是在遍历股票价格数组的过程中,始终记录当前已经出现过的最低买入价格,然后用当前价格减去这个最低买入价格,得到当前可能的最大利润,不断更新这个最大利润值,直到遍历完整个数组。
(二)贪心思路
贪心算法一般步骤的分析:
1. 将问题分解为若干个子问题
- 分析:
在本题中,可以将整个股票交易过程按每一天来看作一个子问题。每一天我们都面临一个决策:是否更新最低买入价格以及基于当前价格和最低买入价格计算可能的最大利润。通过依次处理每一天的情况,最终汇总得到整个交易周期内的最大利润,所以整个问题可以分解为按天来考虑的一系列子问题。 - 初始化变量:
- 设
min_price
为一个较大的值(可以初始化为prices[0]
,因为后续会不断更新它为更小的值),它用来记录到目前为止出现过的最低买入价格。 - 设
max_profit
为0
,它用来记录到目前为止能获取到的最大利润。
- 设
2. 找出适合的贪心策略
- 分析:
贪心策略就是在遍历股票价格数组的过程中,始终保持记录到当前为止所出现过的最低买入价格。因为我们希望买入价格尽可能低,这样在后续任何一天卖出时,才有可能获得最大的利润。所以,每到一天,就比较当天的股票价格和已记录的最低买入价格,如果当天价格更低,就更新最低买入价格,这就是我们确定的贪心策略。
3. 求解每一个子问题的最优解
- 分析:
对于每一天这个子问题,其最优解就是基于当前已经确定的最低买入价格(通过前面的贪心策略不断更新得到),计算当天卖出能获得的最大利润。即通过当天的股票价格减去最低买入价格得到一个差值,如果这个差值大于之前记录的最大利润,就更新最大利润值。 - 遍历数组:
- 从数组的第二个元素(索引为
1
)开始遍历prices
数组,因为第一个元素已经作为初始的min_price
考虑过了。 - 对于每个元素
prices[i]
:- 首先更新
min_price
:比较当前元素prices[i]
和min_price
,如果prices[i]
小于min_price
,则将min_price
更新为prices[i]
。这一步是为了始终记录到目前为止出现过的最低买入价格。 - 然后更新
max_profit
:计算当前价格prices[i]
减去min_price
的差值,得到当前可能的最大利润,将这个差值与max_profit
进行比较,如果差值大于max_profit
,则将max_profit
更新为这个差值。这一步是为了不断更新能获取到的最大利润值。
- 首先更新
- 从数组的第二个元素(索引为
4. 将局部最优解堆叠成全局最优解
- 分析:
在遍历完整个数组后,最后记录下来的最大利润值就是全局最优解。因为在每一天我们都通过贪心策略找到了当天基于最低买入价格能获得的最大利润(局部最优解),随着遍历的进行,不断更新这个最大利润值,最终这个值就代表了在整个交易周期内能够获得的最大利润,也就是将每一天的局部最优解堆叠起来形成了全局最优解。 - 返回结果:
- 遍历完整个数组后,
max_profit
中存储的就是通过一次买入和一次卖出操作所能获取到的最大利润,直接返回max_profit
即可。
- 遍历完整个数组后,
代码对应解释
def maxProfit(prices):if not prices:return 0min_price = prices[0] # 初始化最低买入价格为第一天的价格max_profit = 0 # 初始化最大利润为0# 以下循环对应处理每一天的子问题for price in prices[1:]:# 对应找出适合的贪心策略步骤,更新最低买入价格if price < min_price:min_price = priceprofit = price - min_price # 计算当天基于当前最低买入价格的利润# 对应求解每一个子问题的最优解步骤,更新最大利润if profit > max_profit:max_profit = profitreturn max_profit
class Solution:def maxProfit(self, prices: List[int]) -> int:# 特殊情况:空集if not prices:return 0# 正常情况,初始化min_price = prices[0] # 初始化当前最低买入价格为prices[0]max_profit = 0 # 初始化最大利润为0 # 从索引1(实际2)开始循环遍历股票数组,直接遍历price值# 循环处理每一天的子问题for price in prices[1:]:# 更新当前min_price = min(price, min_price)cur_profit = price - min_pricemax_profit = max(max_profit, cur_profit)return max_profit
在上述代码中:
- 首先判断输入的数组是否为空,如果为空则返回
0
。 - 接着初始化
min_price
和max_profit
。 - 然后通过循环遍历数组,在循环中不断更新
min_price
和max_profit
。 - 最后返回
max_profit
,它就是所能获取到的最大利润。
动态规划解法
- 思路:通过定义状态与状态转移方程解决问题
dp[i]
定义为第i
天卖出股票所能获得的利润dp[i] = max(dp[i - 1], prices[i] - min_price)
是状态方程- 其中,
min_price
是第i
天之前(包括第i
天)的最低股票购入价格
- 代码步骤:
- 特解:空集
- 初始化:
- 收入数组
dp
:一维dp[i]
,长len(prices)
,所有值为0 - 最低买入价格
min_price = prices[0]
- 收入数组
- 循环遍历数组:(从第二天索引1开始)
- 首先更新最低买入价格
dp[i] = max(dp[i - 1], prices[i] - min_price
- 返回最后一个
dp[-1]
- 复杂度分析:
- 时间复杂度:一次循环遍历,每次循环执行的都是比较和赋值,故 O ( n ) O(n) O(n)。
- 空间复杂度:用到长度
n
的数组dp
存储中间状态,故 O ( n ) O(n) O(n)。
def maxProfit(prices):if not prices:return 0n = len(prices)dp = [0] * nmin_price = prices[0]for i in range(1, n):if prices[i] < min_price:min_price = prices[i]dp[i] = max(dp[i - 1], prices[i] - min_price)return dp[-1]
相关文章:
【121. 买卖股票的最佳时机】——贪心算法/动态规划
121. 买卖股票的最佳时机 一、题目难度 简单 三、题目描述 给定一个数组 prices,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择某一天买入这只股票,并选择在未来的某一个不同的日子卖出该股票。设计一个算法来计算你所能获…...
LLMs之Calculate:利用大语言模型技术基于文本内容实现数字计算能力的简介、常用方法、代码实现之详细攻略
LLMs之Calculate:利用大语言模型技术基于文本内容实现数字计算能力的简介、常用方法、代码实现之详细攻略 导读:在基于大语言模型(LLM)技术实现数字计算能力的背景下,文本内容的理解和计算过程涉及多个领域的交叉技术,包括自然语言处理(NLP)、机器学习、以及数值计算。…...
LeetCode题练习与总结:判断子序列--392
一、题目描述 给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一…...

json数据结构的转换
# json可用于赌徒与原件数据的转换(json以字符串的形式储存数据,在通过json进行两种语言的转换时,应先将数据类型转换成列表或字典,再由列表或字典转换成json字符串,最后由json字符串转换成另一种语言的列表或字典数据…...
mysql删除语句:@Update(“TRUNCATE TABLE employee“)讲解
这个 SQL 语句: TRUNCATE TABLE employee是一个 SQL DDL(数据定义语言) 操作,用于清空数据库表中的所有记录,但不会删除表结构(即列和索引等)。 逐部分解释: TRUNCATE:…...
如何修改浏览器指纹?
网络安全日益重要,我们的上网行为变得越来越容易被追踪和分析。其中,浏览器指纹就是一种强大的技术手段,它可以说是你上网的身份象征。 一、浏览器指纹是什么 浏览器指纹是网站和在线平台用来收集关于你的浏览器、设备和网络的详细信息的一…...

实现3D热力图
实现思路 首先是需要用canvas绘制一个2D的热力图,如果你还不会,请看json绘制热力图。使用Threejs中的canvas贴图,将贴图贴在PlaneGeometry平面上。使用着色器材质,更具json中的数据让平面模型 拔地而起。使用Threejs内置的TWEEN&…...
GEE ui界面实现:用户自画多边形, 按面积比例在多边形中自动生成样点,导出多边形和样点shp,以及删除上一组多边形和样点(有视频效果展示)
零、背景 这几天在选样点,发现GEE有强大的ui功能,于是应用在我的工作上。 下述代码实现了几个功能: ①用户可以自己勾勒多边形,随后程序会按面积比例在多边形中自动生成样点,同时根据改多边形的区域生成区域平均月N…...
React diff算法和Vue diff算法的主要区别
React和Vue都是流行的前端框架,它们各自实现了diff算法来优化虚拟DOM的更新过程。以下是React diff算法和Vue diff算法的主要区别: 1. diff策略 React diff算法: React的diff算法主要采用了同层级比较的策略,即它不会跨层级比较节…...

WSL 2 中 FastReport 与 FastCube 的设置方法与优化策略
软件开发人员长期以来一直在思考这个问题:“我们如何才能直接在 Windows 中运行 Linux 应用程序,而无需使用单独的虚拟机?” WSL 技术为这个问题提供了一个可能的答案。WSL 的历史始于 2016 年。当时,其实现涉及使用 Windows 内核…...
《线性代数》学习笔记
列向量无关 上个星期继续学线性代数,一个矩阵,如何判断它是的列向量有几个是线性无关呢?其实有好几个方法。第一个就是一个一个判断。 先选定一个,然后看下这两个,怎么看呢?如果两个列向量线性相关&#…...

Redis三种集群模式:主从模式、哨兵模式和Cluster模式
目录标题 1、背景及介绍2、 Redis 主从复制2.1、主从复制特点2.2、Redis主从复制原理2.3 PSYNC 工作原理2.3.1、启动或重连判断:2.3.2、第一次同步处理:2.3.3、断线重连处理:2.3.4、主节点响应2.3.5、全量同步触发条件:2.3.6、复制…...

CDH大数据平台部署
二、CDH简介 全称Cloudera’s Distribution Including Apache Hadoop。 hadoop的版本 (Apache、CDH、Hotonworks版本) 在公司中一般使用cdh多一些(收费的)、也有公司使用阿里云大数据平台、微软的大数据平台。 国内也有一些平台:星环大数…...

7.4、实验四:RIPv2 认证和触发式更新
源文件 一、引言:为什么要认证和采用触发式更新? 1. RIP v2 认证 RIP(Routing Information Protocol)版本 2 添加了认证功能,以提高网络的安全性。认证的作用主要包括以下几点: 防止路由欺骗 RIP v1 是不…...

【一步步开发AI运动小程序】二十一、如果将AI运动项目配置持久化到后端?
**说明:**本文所涉及的AI运动识别、计时、计数能力,都是基于云智「Ai运动识别引擎」实现。云智「Ai运动识别」插件识别引擎,可以为您的小程序或Uni APP赋于原生、本地、广覆盖、高性能的人体识别、姿态识别、10余种常见的运动计时、计数识别及…...

LED和QLED的区别
文章目录 1. 基础背光技术2. 量子点技术的引入3. 色彩表现4. 亮度和对比度5. 能效6. 寿命7. 价格总结 LED和 QLED都是基于液晶显示(LCD)技术的电视类型,但它们在显示技术、色彩表现和亮度方面有一些关键区别。以下是两者的详细区别ÿ…...

2024 年Postman 如何安装汉化中文版?
2024 年 Postman 的汉化中文版安装教程...
转化古老的Eclipse项目为使用gradle构建
很多古老的Java项目,是使用Eclipse作为IDE开发的。 那么,使用其它IDE的开发者,如何快速地进入这种古老项目的开发呢?或者说,一个Eclipse构建的古老项目,能不能转化成一个IDE无关的项目,进而所有…...
openGauss常见问题与故障处理(二)
2.网络故障定位手段 2.1 网络故障定位手段--常见网络故障引发的异常 在数据库正常工作的情况下,网络层对上层用户是透明的,但数据库在长期运行时,可能会由于各种原因导致出现网络异常或错误。 常见的因网络故障引发的异常有: 1>…...

Mysql 8迁移到达梦DM8遇到的报错
在实战迁移时,遇到两个报错。 一、列[tag]长度超出定义 在mysql中,tag字段的长度是varchar(20),在迁移到DM8后,这个长度不够用了。怎么解决? 在迁移过程中,“指定对象”时,选择转换。 在“列映…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

自然语言处理——文本分类
文本分类 传统机器学习方法文本表示向量空间模型 特征选择文档频率互信息信息增益(IG) 分类器设计贝叶斯理论:线性判别函数 文本分类性能评估P-R曲线ROC曲线 将文本文档或句子分类为预定义的类或类别, 有单标签多类别文本分类和多…...