LeetCode 题目 121:买卖股票的最佳时机

作者介绍:10年大厂数据\经营分析经验,现任字节跳动数据部门负责人。
会一些的技术:数据分析、算法、SQL、大数据相关、python,欢迎探讨交流
欢迎加入社区:码上找工作
作者专栏每日更新:
LeetCode解锁1000题: 打怪升级之旅
python数据分析可视化:企业实战案例
漫画版算法详解
python源码解读
程序员必备的数学知识与应用

题目描述

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

在这里插入图片描述

方法一:一次遍历

解题步骤:
  1. 初始化两个变量:min_price 为正无穷大,用于记录遍历过程中遇到的最低价格;max_profit 为0,用于记录最大利润。
  2. 遍历价格数组,对于每个价格,更新 min_price,并计算以当前价格卖出的利润,更新 max_profit
Python 代码示例
def maxProfit(prices):min_price = float('inf')max_profit = 0for price in prices:if price < min_price:min_price = priceelif price - min_price > max_profit:max_profit = price - min_pricereturn max_profit

方法一通过一次遍历来解决买卖股票的最佳时机问题,下面用 ASCII 图形来详细解释这个方法的工作原理。

一次遍历的图解

考虑一个具体的价格数组示例:

prices = [7, 1, 5, 3, 6, 4]

我们需要找到买入和卖出的最佳时机,以获取最大利润。下面的图解将展示如何在一次遍历中实现这一点。

初始状态
  1. 初始化 min_price 为正无穷大。
  2. 初始化 max_profit 为0。
遍历过程
初始: min_price = inf, max_profit = 0第1天: price = 7min_price = min(inf, 7) = 7max_profit = max(0, 7 - 7) = 0状态: min_price = 7, max_profit = 0第2天: price = 1min_price = min(7, 1) = 1max_profit = max(0, 1 - 1) = 0状态: min_price = 1, max_profit = 0第3天: price = 5min_price = min(1, 5) = 1max_profit = max(0, 5 - 1) = 4状态: min_price = 1, max_profit = 4第4天: price = 3min_price = min(1, 3) = 1max_profit = max(4, 3 - 1) = 4状态: min_price = 1, max_profit = 4第5天: price = 6min_price = min(1, 6) = 1max_profit = max(4, 6 - 1) = 5状态: min_price = 1, max_profit = 5第6天: price = 4min_price = min(1, 4) = 1max_profit = max(5, 4 - 1) = 5状态: min_price = 1, max_profit = 5
结果
  • 最终得到的最大利润是 5,即在价格为 1 的第2天买入,在价格为 6 的第5天卖出。
总结步骤
  • 初始化两个变量 min_pricemax_profit
  • 遍历价格数组,更新 min_price 为遇到的最小价格。
  • 对每个价格,计算如果当天卖出的利润,并更新 max_profit
  • 最后的 max_profit 就是最大利润。

这种方法简单而有效,只需一次遍历就能找到最大利润,同时也避免了复杂的计算和额外的空间开销。

方法二:动态规划

解题步骤:
  1. 使用一个数组 dp 来记录每天结束时可能得到的最大利润。
  2. 第一天的利润为0;从第二天开始,更新当前最小购买价格,并计算当前可能的最大利润。
Python 代码示例
def maxProfit(prices):if not prices:return 0n = len(prices)min_price = prices[0]max_profit = 0for i in range(1, n):min_price = min(min_price, prices[i])max_profit = max(max_profit, prices[i] - min_price)return max_profit

方法三:分治法

解题步骤:
  1. 将价格数组分为两部分,递归地找出左右两部分的最大利润。
  2. 计算跨越两部分的最大利润,即左侧的最低价格和右侧的最高价格之差。
  3. 最大利润是左侧、右侧和跨中三者的最大值。
Python 代码示例
def maxProfit(prices):def maxCrossingProfit(left, right):if left == right:return 0mid = (left + right) // 2min_left = min(prices[left:mid+1])max_right = max(prices[mid+1:right+1])return max(0, max_right - min_left)def divideAndConquer(left, right):if left >= right:return 0mid = (left + right) // 2left_profit = divideAndConquer(left, mid)right_profit = divideAndConquer(mid + 1, right)cross_profit = maxCrossingProfit(left, right)return max(left_profit, right_profit, cross_profit)return divideAndConquer(0, len(prices) - 1)

方法四:前缀最小值与后缀最大值

解题步骤:
  1. 创建两个数组,分别存储从左到右的前缀最小值和从右到左的后缀最大值。
  2. 遍历 prices 数组,计算利用前缀最小和后缀最大计算可能的最大利润。
Python 代码示例
def maxProfit(prices):n = len(prices)if n == 0:return 0min_prefix = [0] * nmax_suffix = [0] * nmin_prefix[0] = prices[0]for i in range(1, n):min_prefix[i] = min(min_prefix[i-1], prices[i])max_suffix[n-1] = prices[n-1]for i in range(n-2, -1, -1):max_suffix[i] = max(max_suffix[i+1], prices[i])max_profit = 0for i in range(n):max_profit = max(max_profit, max_suffix[i] - min_prefix[i])return max_profit

方法五:Kadane算法变形

解题步骤:
  1. 理解为找最大子数组和的问题,其中“价格差”数组是原数组相邻元素的差值。
  2. 使用Kadane算法找到最大子数组和,即为最大利润。
Python 代码示例
def maxProfit(prices):max_current = max_global = 0for i in range(1, len(prices)):max_current = max(0, max_current + prices[i] - prices[i-1])if max_current > max_global:max_global = max_currentreturn max_global

算法分析

  • 时间复杂度:所有方法均为 (O(n)),其中 (n) 是数组长度,因为每个方法都只遍历了一次或两次数组。
  • 空间复杂度
    • 方法一和五:(O(1)),只使用了常数空间。
    • 方法二、三和四:(O(n)),因为使用了额外的数组。

不同算法的优劣势对比

  • 一次遍历(方法一)和Kadane算法变形(方法五)非常高效,简单,易于实现。
  • 动态规划(方法二)直观,易于理解,常用于面试中解释。
  • 分治法(方法三)和前缀最小值与后缀最大值(方法四)提供了不同的视角,适合深入理解问题的结构,但实现较为复杂。

应用示例

这些方法可以应用于金融分析领域,特别是在算法交易和股票市场分析中,用于计算和预测最优买卖点,从而最大化投资回报。

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

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

相关文章

“知识世界”项目的自动化测试

目录 1.项目介绍 1.1 项目功能介绍 2. 项目测试 2.1 需求分析 2.2 测试计划 2.3 设计测试用例 &#xff08;1&#xff09; 设计 登录 的测试用例 &#xff08;2&#xff09;设计 文章列表页 的测试用例 &#xff08;3&#xff09;设计 详情页 的测试用例 &#xff08…

车载测试系列:车载常见面试题

自我介绍项目介绍项目具体是怎么测试的&#xff1f;CANoe是怎么使用的&#xff1f;台架是怎么搭建的&#xff1f;台架怎么测试的&#xff1f;诊断服务是怎么测试的&#xff1f;功能寻址和物理寻找的区别10服务有什么会话&#xff1f;11服务怎么确定软件复位和硬件复位是什么&am…

Gauge32类型的数据转换成int类型的数据

提前编译号snmp的库 #include <iostream> #include <libsnmp.h>#include "snmp_pp/snmp_pp.h"#ifdef WIN32 #define strcasecmp _stricmp #endif#ifdef SNMP_PP_NAMESPACE using namespace Snmp_pp; #endifusing namespace std; using namespace Snmp_pp…

JAVA抽象类,接口与内部类,常用API知识总结

文章目录 抽象类和抽象方法抽象类的定义格式抽象方法的定义格式注意事项 接口定义和使用成员特点和类之间的关系新增JDK8新增方法JDK9新增方法 总结设计模式 内部类使用场景分类成员内部类获取内部类对象访问成员变量 静态内部类局部内部类匿名内部类格式使用场景 示例 常用API…

JVM内存信息分析

jmap安装使用 java - version 查看已安装jdk的版本 sudo apt-get install openjdk-11-jdk-headless 安装jmap jmap -version 验证是否安装成功 jmap -dump:live,formatb,filexxxx.hprof pid 导出jvm内存信息&#xff0c;pid一般为java进程id内存信息分析 strings xxx.phrof |…

459.重复的子字符串

给定一个非空的字符串&#xff0c;判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母&#xff0c;并且长度不超过10000。 示例 1: 输入: "abab"输出: True解释: 可由子字符串 "ab" 重复两次构成。 示例 2: 输入: "aba&q…

chap5 I/O管理

目录 一、I/O设备基本概念和分类 304 1.concept 2.classification &#xff08;1&#xff09;根据信息交换单位&#xff08;可能考&#xff09; 1)字符设备 2)块设备 &#xff08;2&#xff09;传输速率&#xff08;以下了解即可&#xff09; &#xff08;3&#xff09;…

R语言数据分析案例-股票可视化分析

一、数据整合的对象 # Loading necessary libraries library(readxl) library(dplyr)# Reading the data from Excel files data_1 <- read_excel("云南白药.xlsx") data_2 <- read_excel("冰山.xlsx")二、数据整合的代码 # Reading the data from…

OBS插件--音频采集

音频采集 音频采集是一款 源 插件,类似于OBS的win-capture/game-capture&#xff0c;允许从特定应用程序捕获音频&#xff0c;而不是捕获整个系统的音频。避免了因为特定音频的采集而需要引入第三方软件&#xff0c;而且时延也非常低。 下面截图演示下操作步骤&#xff1a; 首…

【顺序程序设计-谭浩强适配】(适合专升本、考研)

无偿分享学习资料&#xff0c;需要的小伙伴评论区或私信dd。。。 无偿分享学习资料&#xff0c;需要的小伙伴评论区或私信dd。。。 无偿分享学习资料&#xff0c;需要的小伙伴评论区或私信dd。。。 完整资料如下&#xff1a;纯干货、纯干货、纯干货&#xff01;&#xff01;…

WEB后端复习——监听器、过滤器

Listener监听器 是Servlet规范中定义的一种特殊类&#xff0c;它用于监听web应用程序中的ServletContext, HttpSession和ServletRequest等域对象的创建与销毁事件&#xff0c;以及监听这些域对象中的属性发生修改的事件。 注解WebListener 1.ServletContextListener 监听Serv…

U盘文件遇损?拯救“文件或目录损坏且无法读取”的秘籍!

在数字化时代&#xff0c;U盘已成为我们日常生活与工作中不可或缺的数据存储和传输工具。然而&#xff0c;有时我们可能会遇到一个非常令人沮丧的问题——U盘中的文件或目录突然损坏且无法读取。这种突发状况往往让人措手不及&#xff0c;甚至可能引发数据丢失的严重后果。那么…

打印图案(金字塔)头歌作业

题目: 任务描述 本关任务&#xff1a;编写一个程序&#xff0c;输出堆叠式的金字塔图案。 输入n个字符&#xff0c;按以下原则输出&#xff1a;【参考样例】 1)第1个字符为一层金字塔图案&#xff0c;第2个字符为两层金字塔图案&#xff0c;第3个字符为三层金字塔图案&#x…

相同的树——java

给你两棵二叉树的根节点 p 和 q &#xff0c;编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同&#xff0c;并且节点具有相同的值&#xff0c;则认为它们是相同的。 示例 1&#xff1a; 输入&#xff1a;p [1,2,3], q [1,2,3] 输出&#xff1a;true示例 2&…

[华为OD] B卷 树状结构查询 200

题目&#xff1a; 通常使用多行的节点、父节点表示一棵树&#xff0c;比如 西安 陕西 陕西 中国 江西 中国 中国 亚洲 泰国 亚洲 输入一个节点之后&#xff0c;请打印出来树中他的所有下层节点 输入描述 第一行输入行数&#xff0c;下面是多行数据&#xff0c;每行以空…

C++青少年简明教程:基础知识

C青少年简明教程&#xff1a;基础知识 电脑程序设计&#xff08;Computer programming&#xff09;&#xff0c;或称程序设计&#xff08;programming&#xff09;&#xff0c;是给出解决特定问题程序的过程&#xff0c;程序设计往往以某种程序设计语言为工具&#xff0c;给出这…

关于一致性,你该知道的事儿(上)

关于一致性&#xff0c;你该知道的事儿&#xff08;上&#xff09; 前言一、缓存一致性二、内存模型一致性三、事务一致性四、分布式事务一致性4.1 分布式系统的一些挑战4.2 关于副本的一些概念4.3 分布式事务之共识问题4. 3.1 PC(two-phase commit, 2PC)4.3.2 Raft 三、后记参…

公有云Linux模拟TCP三次挥手与四次握手(Wireshark抓包验证版)

目录 写在前面环境准备实验步骤1. 安装nc工具2. 使用nc打开一个连接2.1 公有云-安全组放行对应端口&#xff08;可选&#xff09; 3. 打开Wireshark抓包工具4. 新开终端&#xff0c;进行连接5. 查看抓包文件&#xff0c;验证TCP三次握手与四次挥手TCP三次握手数据传输TCP四次挥…

Netty源码分析二NioEventLoop 剖析

剖析方向 NioEventLoop是一个重量级的类&#xff0c;其中涉及到的方法都有很复杂的继承关系&#xff0c;调用链&#xff0c;要想把源码全部过一遍工作量实在是太大了&#xff0c;于是小编就基于下面的这些常见的问题来对NioEventLoop的源码来进行剖析 1.Seletor何时创建 1.1Se…

【408真题】2009-08

“接”是针对题目进行必要的分析&#xff0c;比较简略&#xff1b; “化”是对题目中所涉及到的知识点进行详细解释&#xff1b; “发”是对此题型的解题套路总结&#xff0c;并结合历年真题或者典型例题进行运用。 涉及到的知识全部来源于王道各科教材&#xff08;2025版&…