news 2026/4/18 8:25:24

算法题 股票价格跨度

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
算法题 股票价格跨度

股票价格跨度

问题描述

编写一个StockSpanner类,它收集某些股票的每日收盘价,并返回当日价格的跨度

价格跨度:今天价格大于或等于过去连续x天价格的天数(包括今天)。

具体来说,如果prices = [100,80,60,70,60,75,85],那么spans = [1,1,1,2,1,4,6]

示例

StockSpannerstockSpanner=newStockSpanner();stockSpanner.next(100);// 返回 1stockSpanner.next(80);// 返回 1stockSpanner.next(60);// 返回 1stockSpanner.next(70);// 返回 2 (70 >= 60)stockSpanner.next(60);// 返回 1stockSpanner.next(75);// 返回 4 (75 >= 60, 70, 60)stockSpanner.next(85);// 返回 6 (85 >= 75, 60, 70, 60, 80)

算法思路

单调栈

  1. 核心思想
    • 维护一个单调递减栈,存储(price, span)
    • 当新价格到来时,弹出所有小于等于当前价格的元素
    • 当前跨度 = 弹出元素的跨度之和 + 1

代码实现

方法一:单调栈

importjava.util.*;classStockSpanner{/** * 股票价格跨度计算器 * * 核心数据结构:单调递减栈 * 栈中存储 (price, span) 对 */privateDeque<int[]>stack;// int[0] = price, int[1] = spanpublicStockSpanner(){stack=newArrayDeque<>();}/** * 计算当前价格的跨度 * * 时间复杂度: O(1) * 空间复杂度: O(n) * * @param price 当前股票价格 * @return 价格跨度 */publicintnext(intprice){intspan=1;// 弹出所有小于等于当前价格的元素while(!stack.isEmpty()&&stack.peek()[0]<=price){span+=stack.pop()[1];}// 将当前价格和跨度压入栈stack.push(newint[]{price,span});returnspan;}}

方法二:使用两个栈

classStockSpanner{// 分别存储价格和跨度privateStack<Integer>prices;privateStack<Integer>spans;publicStockSpanner(){prices=newStack<>();spans=newStack<>();}publicintnext(intprice){intspan=1;// 弹出所有小于等于当前价格的价格while(!prices.isEmpty()&&prices.peek()<=price){prices.pop();span+=spans.pop();}prices.push(price);spans.push(span);returnspan;}}

算法分析

  • 时间复杂度:O(1)

    • 每个元素最多被压入和弹出一次
    • n 次操作的总时间复杂度为 O(n)
    • 平均每次操作 O(1)
  • 空间复杂度:O(n)

    • 最坏情况下栈中存储所有价格(严格递减序列)
    • 平均情况下空间使用较少

算法过程

1:prices = [100,80,60,70,60,75,85]

初始: stack = [] next(100): - stack为空,span = 1 - stack = [(100,1)] - 返回 1 next(80): - 80 < 100,不弹出 - span = 1 - stack = [(100,1), (80,1)] - 返回 1 next(60): - 60 < 80,不弹出 - span = 1 - stack = [(100,1), (80,1), (60,1)] - 返回 1 next(70): - 70 > 60,弹出(60,1),span = 1 + 1 = 2 - 70 < 80,停止 - stack = [(100,1), (80,1), (70,2)] - 返回 2 next(60): - 60 < 70,不弹出 - span = 1 - stack = [(100,1), (80,1), (70,2), (60,1)] - 返回 1 next(75): - 75 > 60,弹出(60,1),span = 1 + 1 = 2 - 75 > 70,弹出(70,2),span = 2 + 2 = 4 - 75 < 80,停止 - stack = [(100,1), (80,1), (75,4)] - 返回 4 next(85): - 85 > 75,弹出(75,4),span = 1 + 4 = 5 - 85 > 80,弹出(80,1),span = 5 + 1 = 6 - 85 < 100,停止 - stack = [(100,1), (85,6)] - 返回 6

测试用例

importjava.util.*;publicclassTest{publicstaticvoidmain(String[]args){// 测试用例1:标准示例StockSpannerspanner1=newStockSpanner();System.out.println("Test 1:");System.out.println("100: "+spanner1.next(100));// 1System.out.println("80: "+spanner1.next(80));// 1System.out.println("60: "+spanner1.next(60));// 1System.out.println("70: "+spanner1.next(70));// 2System.out.println("60: "+spanner1.next(60));// 1System.out.println("75: "+spanner1.next(75));// 4System.out.println("85: "+spanner1.next(85));// 6// 测试用例2:严格递增序列StockSpannerspanner2=newStockSpanner();System.out.println("10: "+spanner2.next(10));// 1System.out.println("20: "+spanner2.next(20));// 2System.out.println("30: "+spanner2.next(30));// 3System.out.println("40: "+spanner2.next(40));// 4// 测试用例3:严格递减序列StockSpannerspanner3=newStockSpanner();System.out.println("40: "+spanner3.next(40));// 1System.out.println("30: "+spanner3.next(30));// 1System.out.println("20: "+spanner3.next(20));// 1System.out.println("10: "+spanner3.next(10));// 1// 测试用例4:所有相同价格StockSpannerspanner4=newStockSpanner();System.out.println("50: "+spanner4.next(50));// 1System.out.println("50: "+spanner4.next(50));// 2System.out.println("50: "+spanner4.next(50));// 3System.out.println("50: "+spanner4.next(50));// 4// 测试用例5:单个价格StockSpannerspanner5=newStockSpanner();System.out.println("100: "+spanner5.next(100));// 1// 测试用例6:大数值StockSpannerspanner6=newStockSpanner();System.out.println("1000000: "+spanner6.next(1000000));// 1System.out.println("500000: "+spanner6.next(500000));// 1System.out.println("750000: "+spanner6.next(750000));// 2// 测试用例7:复杂StockSpannerspanner7=newStockSpanner();int[]prices={29,91,62,76,51};for(intprice:prices){System.out.println(price+": "+spanner7.next(price));}// 测试用例8:峰值StockSpannerspanner8=newStockSpanner();int[]prices2={10,20,30,40,30,20,10,50};for(intprice:prices2){System.out.println(price+": "+spanner8.next(price));}}}

关键点

  1. 单调栈

    • 栈中价格严格递减
    • 每个元素存储价格和对应的跨度
    • 弹出操作正确累加跨度
  2. 跨度计算

    • 被弹出的元素都是连续的且价格 ≤ 当前价格
  3. 边界情况处理

    • 空栈情况
    • 相同价格的处理(≤ 条件)
    • 严格递增/递减序列

常见问题

  1. 为什么使用单调递减栈而不是递增栈?

    • 需要找到"最近的更大价格"
    • 单调递减栈的栈顶就是最近的更大价格
  2. 如何处理相同价格?

    • 使用<=条件,相同价格也会被弹出
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 3:36:00

(7-1)自动驾驶中的动态环境路径重规划:D*算法介绍

在自动驾驶领域&#xff0c;车辆不仅要应对复杂的静态交通环境&#xff0c;还要实时处理动态变化的路况&#xff0c;如突然出现的障碍物、交通信号变化等。因此&#xff0c;动态环境下的路径重规划能力至关重要。本章将深入探讨动态路径规划算法&#xff0c;特别是 D* 算法&…

作者头像 李华
网站建设 2026/4/18 3:36:35

LLM开发工程师进阶指南:从技术掌握到价值创造的三阶成长路径

LLM开发工程师进阶指南&#xff1a;从技术掌握到价值创造的三阶成长路径 【免费下载链接】llm-cookbook 面向开发者的 LLM 入门教程&#xff0c;吴恩达大模型系列课程中文版 项目地址: https://gitcode.com/datawhalechina/llm-cookbook 想要在AI浪潮中脱颖而出&#xf…

作者头像 李华
网站建设 2026/4/16 13:20:02

数字孪生软件外包的流程

数字孪生&#xff08;Digital Twin&#xff09;软件外包的流程比普通 App 或网站开发复杂得多&#xff0c;因为它涉及物理世界建模、实时数据集成、仿真计算以及高保真渲染四个维度的深度整合。以下是数字孪生软件外包的标准执行流程&#xff0c;分为六个核心阶段&#xff1a;第…

作者头像 李华
网站建设 2026/4/18 8:06:18

论文重复率太高如何解决?这些AI改写工具可快速帮你降低相似度

五大降重工具核心对比 工具名称 处理速度 降重幅度 专业术语保留 适用场景 aicheck 20分钟内 40%→7% 完全保留 高重复率论文紧急处理 秒篇 5-10分钟 45%→8% 完全保留 快速降重需求 白果AI 15分钟 30%→10% 学科词库保护 学术论文精细降重 文赋AI 5分钟 …

作者头像 李华
网站建设 2026/4/18 4:50:36

论文查重没通过?推荐使用AI工具智能降重,迅速优化文本内容

五大降重工具核心对比 工具名称 处理速度 降重幅度 专业术语保留 适用场景 aicheck 20分钟内 40%→7% 完全保留 高重复率论文紧急处理 秒篇 5-10分钟 45%→8% 完全保留 快速降重需求 白果AI 15分钟 30%→10% 学科词库保护 学术论文精细降重 文赋AI 5分钟 …

作者头像 李华