股票价格数据流设计与实现详解 —— StockPrice 类的设计与优化
题目描述
给你一个股票价格的数据流,数据流中每条记录包含一个时间戳和该时间点对应的股票价格。由于市场波动,数据流中:
- 记录可能不是按时间顺序到来的;
- 某些时间戳的价格记录可能是错误的,若后续出现同一时间戳的记录,则新的记录更正之前的错误。
请设计一个 StockPrice 类,实现以下功能:
- 更新某时间戳的股票价格(若该时间戳已有价格则更正);
- 查询当前最新时间戳的股票价格;
- 查询当前所有记录中的最高股票价格;
- 查询当前所有记录中的最低股票价格。
API 设计:
class StockPrice:
def __init__(self):
# 初始化,当前无股票价格记录
def update(self, timestamp: int, price: int) -> None:
# 在时间点 timestamp 更新股票价格为 price
def current(self) -> int:
# 返回当前最新时间戳对应的股票价格
def maximum(self) -> int:
# 返回当前所有股票价格的最高价
def minimum(self) -> int:
# 返回当前所有股票价格的最低价
示例说明
输入:
["StockPrice", "update", "update", "current", "maximum", "update", "maximum", "update", "minimum"]
[[], [1, 10], [2, 5], [], [], [1, 3], [], [4, 2], []]
执行过程及输出:
stockPrice = StockPrice()
stockPrice.update(1, 10) # 时间戳为1,价格10
stockPrice.update(2, 5) # 时间戳为2,价格5
print(stockPrice.current()) # 最新时间戳为2,价格为5
print(stockPrice.maximum()) # 最高价格为10
stockPrice.update(1, 3) # 更正时间戳1的价格为3
print(stockPrice.maximum()) # 最高价格变为5(因为时间戳1价格从10变3)
stockPrice.update(4, 2) # 时间戳4价格2
print(stockPrice.minimum()) # 最低价格为2
输出:
5
10
5
2
解题分析
1. 需求分析
- 需要按时间戳快速更新价格,且支持价格覆盖(更正)。
- 需要快速找到当前最新时间戳对应的价格。
- 需要快速查询最高价和最低价。
- 价格更新时,要能正确更新最高价和最低价(支持多次更新同一时间戳的价格)。
- 最高价和最低价查询操作需要高效。
2. 关键点
- 记录数据可能乱序到达。
- 旧价格可能被更正(相同时间戳后续更新),因此最高/最低价堆中旧的价格会失效,需要能“跳过”。
- 需要快速访问最新时间戳。
解题方法
核心数据结构设计
- 哈希表
**timestamp_price_map**:- 维护时间戳到当前最新价格的映射。
- 支持快速更新和查询。
- 最大堆
**max_heap**和最小堆**min_heap**:max_heap存储元素为(-price, timestamp),方便快速获取最大价格。min_heap存储元素为(price, timestamp),方便快速获取最小价格。- 堆中可能存在旧的过期记录,需要在查询时惰性删除(跳过失效项)。
- 变量
**latest_timestamp**:- 记录当前数据中最大时间戳,方便
current()查询。
- 记录当前数据中最大时间戳,方便
具体操作实现
update(timestamp, price)
- 将
timestamp_price_map[timestamp] = price更新或新增。 - 更新
latest_timestamp = max(latest_timestamp, timestamp)。 - 将新
(price, timestamp)推入max_heap和min_heap。
注意:旧的堆中元素并不立即删除,等待查询时惰性删除。
current()
- 直接返回
timestamp_price_map[latest_timestamp]。
maximum()
- 不断检查
max_heap堆顶元素(neg_price, timestamp)是否仍有效(即timestamp_price_map[timestamp] == -neg_price)。 - 如果无效则弹出,直到找到有效最大值,返回它。
minimum()
- 类似
maximum(),从min_heap取堆顶,判断有效性,弹出无效元素,返回有效最小值。
代码实现
import heapq
class StockPrice:
def __init__(self):
self.timestamp_price_map = {}
self.max_heap = [] # (-price, timestamp)
self.min_heap = [] # (price, timestamp)
self.latest_timestamp = 0
def update(self, timestamp: int, price: int) -> None:
self.timestamp_price_map[timestamp] = price
self.latest_timestamp = max(self.latest_timestamp, timestamp)
heapq.heappush(self.max_heap, (-price, timestamp))
heapq.heappush(self.min_heap, (price, timestamp))
def current(self) -> int:
return self.timestamp_price_map[self.latest_timestamp]
def maximum(self) -> int:
while True:
neg_price, timestamp = self.max_heap[0]
if self.timestamp_price_map[timestamp] == -neg_price:
return -neg_price
heapq.heappop(self.max_heap)
def minimum(self) -> int:
while True:
price, timestamp = self.min_heap[0]
if self.timestamp_price_map[timestamp] == price:
return price
heapq.heappop(self.min_heap)
复杂度分析
| 操作 | 时间复杂度 | 备注 |
|---|---|---|
| update | O(log N) | 插入堆元素 |
| current | O(1) | 直接哈希表查找 |
| maximum | 摊还 O(log N) | 可能弹出过期堆元素 |
| minimum | 摊还 O(log N) | 同上 |
空间复杂度为 O(N),N 是更新的总次数。
方法比较
| 方案 | 优点 | 缺点 |
|---|---|---|
| 维护哈希表 + 最大/最小堆 | 查询高效,支持乱序更新,惰性删除简单 | 堆空间可能大,需惰性清理 |
| 线性扫描(简单数组) | 实现简单 | 查询慢,O(N) 不适合大量数据 |
| 平衡树(红黑树/AVL等) | 有序数据结构,查询快 | 复杂度较高,语言支持限制 |
结语
这道题考察了数据结构设计与更新机制,重点在于如何处理“旧数据失效”问题,利用惰性删除实现高效维护最大/最小值,同时通过哈希表快速更新同时间戳的价格。
代码简洁、性能优秀,适合面试和实际系统的设计需求。
348

被折叠的 条评论
为什么被折叠?



