流式不同元素的运行计数
Stream Running Distinct Count
开始编码给一条整数事件流 values,长度 N(0 ≤ N ≤ 10⁴,每个值都是 int)。每来一个事件,输出到此为止见过的不同值的运行个数——也就是返回一个长度等于 values 的列表,output[i] = values[:i+1] 中的不同值个数。处理完整条流后,按顺序返回每个事件的计数。
干净的做法是一次线性扫描 + 一个哈希集合 seen。对每个 x:把它加入集合(已存在就是无操作),然后发出 len(seen)。集合在插入之后的大小恰好就是当前的运行不同计数:x 是新值就 +1,x 是重复就不变。每个事件平均 O(1),总时间 O(N),空间 O(K),K 是不同值的数量。
Examples
solution([5, 3, 5, 7, 3, 9]) 返回 [1, 2, 2, 3, 3, 4]。逐步走一遍:吃 5 → seen={5} → 输出 1。吃 3 → seen={3, 5} → 输出 2。吃 5 → 已在集合里,集合不变 → 输出 2。吃 7 → seen={3, 5, 7} → 输出 3。吃 3 → 重复 → 输出 3。吃 9 → seen={3, 5, 7, 9} → 输出 4。注意输出长度与输入完全一致:每个事件都产生一个 count,包括「值是重复的」那种事件。
solution([]) 返回 []。零个事件就零个输出。空列表是合法输入;不要特判成 [0] 或 None。循环根本不进入,最初的空输出列表原样返回。
solution([7, 7, 7, 7, 7]) 返回 [1, 1, 1, 1, 1]。第一个事件之后 seen = {7},再加四个 7 集合大小始终是 1。输出是五个 1——每个事件一个,哪怕 distinct 计数从未变化。坑:不要因为「值没变」就跳过输出。规范是「每个事件一个计数」,不是「每次变化一个计数」。
签名见 stubs/stub.py。
Practical context
运行不同计数是一族流式微观结构基数追踪原语里最简单的一员,这一族在实战里到处都是。最有代表性的用例是行情带子上的每秒不同标的数监控:随着报价按 venue + symbol 一条条流进来,交易所运营台需要一个实时仪表,看最近 1 秒 / 1 分钟 / 整段会话里有多少个不同的标的成交过——既是流动性广度信号(不同标的数突然飙升常常先于指数调仓或 ETF 申赎事件),也是数据流健康信号(市场开盘期间不同标的数突然平直,往往意味着某段订阅悄无声息地掉了)。同一个原语——流上集合的基数——也撑起了「每账户独立交易对手数」的合规计数器、「每会话独立 IP 数」的 API 限流逻辑、以及多路市场数据接入里的「独立 trade-id 去重」。当流的基数无界、把每个不同值都留在内存里太贵时,生产做法是上一个概率草图(HyperLogLog 用 ~12KB 内存就能给 ε ≈ 1% 的误差,与真实基数无关),但精确版的 set 仍然是合适的起点:它把语义钉死,让测试用例可以一眼校验,是每个工程师在判定「基数大到值得用草图」之前最先伸手去拿的工具。
约束条件
- 0 ≤ N ≤ 10^4,N = len(values)
- values[i] 是整数(负数、零、正数都允许,量级最大 ±10^9)
- 返回长度与 `values` 相同的列表,output[i] = values[:i+1] 中不同值的个数
- 空输入返回空列表
样例
Case 1 · typical: mixed stream with one repeat
输入: [[5,3,5,7,3,9]]
期望: [1,2,2,3,3,4]
一边读一边维护一个集合 seen。读 5 → seen={5},输出 1。读 3 → seen={3,5},输出 2。读 5 → 已在集合里,集合不变还是大小 2,输出 2。读 7 → seen={3,5,7},输出 3。读 3 → 已存在,仍是 3。读 9 → seen={3,5,7,9},输出 4。注意每个事件都要发一个 count,包括「重复值不增加 distinct 数」的事件,输出长度永远等于输入长度。
Case 2 · edge: empty input → empty output
输入: [[]]
期望: []
0 个事件就 0 个输出。空列表是合法输入;不要返回 [0] 或 None。 set 初始化为空,循环不进入,直接返回空列表。
Case 3 · edge: all values identical → constant 1
输入: [[7,7,7,7,7]]
期望: [1,1,1,1,1]
所有事件都是同一个值,第一个事件之后 distinct 集合就是 {7},再加多少个 7 集合大小都是 1。每个事件仍要输出一次(共 5 个 1),不要因为「值没变」就跳过输出。
最近提交
还没有提交记录。
编码区
实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
Case 1 · typical: mixed stream with one repeat
输入: [[5,3,5,7,3,9]]
期望: [1,2,2,3,3,4]
一边读一边维护一个集合 seen。读 5 → seen={5},输出 1。读 3 → seen={3,5},输出 2。读 5 → 已在集合里,集合不变还是大小 2,输出 2。读 7 → seen={3,5,7},输出 3。读 3 → 已存在,仍是 3。读 9 → seen={3,5,7,9},输出 4。注意每个事件都要发一个 count,包括「重复值不增加 distinct 数」的事件,输出长度永远等于输入长度。
Case 2 · edge: empty input → empty output
输入: [[]]
期望: []
0 个事件就 0 个输出。空列表是合法输入;不要返回 [0] 或 None。 set 初始化为空,循环不进入,直接返回空列表。
Case 3 · edge: all values identical → constant 1
输入: [[7,7,7,7,7]]
期望: [1,1,1,1,1]
所有事件都是同一个值,第一个事件之后 distinct 集合就是 {7},再加多少个 7 集合大小都是 1。每个事件仍要输出一次(共 5 个 1),不要因为「值没变」就跳过输出。