← 返回编程题库
coding-cross-feed-cum-count-lead-exchanges中等免费版2000ms未尝试

跨源行情累计计数领先权交换次数

Cross-Feed Cumulative-Count Lead Exchanges

开始编码

一位交易员同时跑两条同标的的市场数据 feed——一条同机房主 feed(ts_a)、一条异地灾备 feed(ts_b),需要给当日 SLO 仪表盘出一项 feed 平衡健康度指标:当天累计计数的「领先权」在两路 feed 之间换手了多少次。请实现 solution(ts_a: list[int], ts_b: list[int]) -> int,返回合并时间线上的领先权交换总次数。任一流为空时返回 0(其中一侧恒为 0,不可能发生交换)。

ts_ats_b 都是严格升序的整数毫秒时间戳数组。沿合并时间线按时间先后扫描;在每个唯一时刻 t(取自 ts_a ∪ ts_b)原子地更新 cum_acum_b 为该 feed 中时间戳 <= t 的事件计数,再计算 diff(t) = cum_a(t) - cum_b(t)。「领先权交换」定义为 diff 在两次相邻非零符号之间发生严格反号——途中经过 0 的状态不算一次交换、而算零次(一次「打平」),除非随后下一个非零符号与上一次非零符号相反,那才整体计为一次交换。

边界情形:

  • len(ts_a) == 0len(ts_b) == 0,返回 0——一侧恒为 0、不可能发生交换。
  • 两条流完全相同(ts_a == ts_b)时 diff 恒为 0,返回 0
  • ts_a 整段位于 ts_b 之前 → cum_a 先领先,再被 cum_b 追上;若 cum_b 最终超过 cum_a 则答案为 1,否则为 0
  • 严格交替且两路在每个共同时刻都打平 → 领先权永远不换手,返回 0
  • 跨 feed 时间戳同点(相同 t 同时出现在两路)必须原子处理:先把 cum_acum_b 在该时刻一起加完再读 sign(diff)——否则会让伪中间符号渗入 last_nonzero_sign 并污染后续比较。

例如:

ts_a = [1, 4, 5, 8]
ts_b = [2, 3, 6, 7]

solution(ts_a, ts_b) 返回 3。沿合并时间线扫描:t=1(cum_a, cum_b) = (1, 0)diff=+1(A 领先,last_nonzero_sign = +1);t=2(1, 1)diff=0(打平,last_nonzero_sign 保持);t=3(1, 2)diff=-1,从 +1 严格反号——交换 1(last_nonzero_sign = -1);t=4(2, 2)diff=0(打平);t=5(3, 2)diff=+1,从 -1 反号——交换 2;t=6(3, 3)diff=0(打平);t=7(3, 4)diff=-1,从 +1 反号——交换 3;t=8(4, 4)diff=0。总计 3。

实践背景

当两条冗余 feed 并行跑时,全天累计领先权交换次数是 SLO 仪表盘上一项干净的 feed 平衡健康度指标。交换次数多 = 两路 feed 节奏接近、彼此势均力敌;交换次数为 0 或 1 = 某一路压制式地领先、另一路被饿死,往往提示单边丢包、路由不对称、或灾备复制流水线被卡住。指标按日聚合,对全天两路心跳流跑一次。生产里心跳量动辄数十亿条,所以线性扫描的 O(N + M) 才是把日报压到分钟级而不是小时级的关键。

约束条件

  • 0 ≤ N、M ≤ 1500,其中 N = len(ts_a)、M = len(ts_b)。算法保持 O(N + M) 复杂度,从而在更大规模输入上也能在时限内完成。
  • 0 ≤ ts_a[i] ≤ 1e9 且 0 ≤ ts_b[j] ≤ 1e9;两个数组均严格升序(单条 feed 内无重复值)。允许跨 feed 时间戳同点(相同 `t` 同时出现在 ts_a 与 ts_b 中),且必须做原子处理。
  • 输出为单一非负整数,范围 `[0, N + M - 1]`——合并时间线上的领先权交换总次数。
  • 当 ts_a 或 ts_b 任一为空时返回 `0`——一侧恒为 0、diff 永远不反号,不可能发生交换。两侧都为空也返回 `0`。
  • 一次「领先权交换」定义为 `diff(t) = cum_a(t) - cum_b(t)` 在两次相邻非零符号之间发生严格反号。「途经零」的路径塌缩为一次交换——`+3 -> 0 -> -2` 算 1 次(不是 0、也不是 2)。两条流完全相同(`ts_a == ts_b`)时 diff 恒为 0,结果为 0。
  • 若任一输入未排序或单条 feed 内出现重复,行为未定义;调用方负责输入校验。

样例

Case 1 · statement-example: alternating with three exchanges

输入: [[1,4,5,8],[2,3,6,7]]

期望: 3

题面例题:合并时间线 1,2,3,4,5,6,7,8,diff 序列为 +1,0,-1,0,+1,0,-1,0;非零符号链 +1 -> -1 -> +1 -> -1 共 3 次严格反号,故答案为 3。

Case 2 · visible: both feeds empty -> 0

输入: [[],[]]

期望: 0

两侧均为空,diff 恒为 0,没有任何符号反转,返回 0。

Case 3 · visible: ts_a empty -> 0

输入: [[],[1,2,3,4,5]]

期望: 0

ts_a 为空时 cum_a 恒为 0,diff = -cum_b 永远 <= 0,从未变成正号,故没有从负到正的反转,返回 0。

Case 4 · visible: ts_b empty -> 0

输入: [[10,20,30],[]]

期望: 0

ts_b 为空时 cum_b 恒为 0,diff = cum_a 永远 >= 0,从未变成负号,故没有正到负的反转,返回 0。

Case 5 · visible: identical streams -> 0

输入: [[1,2,3,4,5],[1,2,3,4,5]]

期望: 0

两路完全相同时,每个时刻原子地各自 +1,diff 始终为 0,从未达到非零符号,故 0 次交换。

Case 6 · typical: a-leads-then-b-overtakes

输入: [[1,2,3],[10,11,12,13]]

期望: 1

t=1..3 时 cum_a 一路领先 (diff = +1, +2, +3);t=10..12 cum_b 追平到 0;t=13 cum_b 超出,diff = -1,从 +1 严格反号,唯一一次交换。

Case 7 · typical: a-leads-but-b-never-catches-up

输入: [[1,2,3,4],[10,11]]

期望: 0

cum_a 全程领先,最终 cum_b 仍未追上 cum_a,diff 始终 > 0,无符号反转,返回 0。

Case 8 · typical: b-leads-but-a-never-catches-up

输入: [[10,11],[1,2,3,4]]

期望: 0

cum_b 全程领先,最终 cum_a 仍未追上,diff 始终 < 0,无符号反转,返回 0。

Case 9 · typical: zero-pass-through-counts-as-one

输入: [[1,2,3],[4,5,6,7,8]]

期望: 1

diff 走 +1,+2,+3,+2,+1,0,-1,-2;从最后一次非零符号 +1 经过 0 后变为 -1,整段塌缩为 1 次严格反号交换。

Case 10 · typical: alternating-a-leads-shared-tie-instants

输入: [[1,3,5,7],[2,4,6,8]]

期望: 0

A 总是先到,每对相邻时刻 diff 走 +1,0,+1,0,+1,0,+1,0;非零符号始终为 +1,无反号,0 次交换。

Case 11 · typical: same-event-count-but-interleaved-no-flip

输入: [[2,4,6,8],[1,3,5,7]]

期望: 0

B 总是先到一拍,diff 走 -1,0,-1,0,-1,0,-1,0;非零符号始终为 -1,无反号,0 次交换。

Case 12 · typical: cross-flip-twice-with-zero-passes

输入: [[1,2,9,10,11],[3,4,5,6]]

期望: 2

t=1,2 时 A 领先 (diff +1,+2);t=3..6 时 B 追上并反超:diff 走 +1, 0, -1, -2,从 +1 经 0 跌到 -1 计 1 次交换;t=9 (3,4,-1)、t=10 (4,4,0)、t=11 (5,4,+1),从 -1 经 0 升到 +1 又计 1 次交换;共 2 次。

Case 13 · typical: cross-feed-tie-mid-timeline

输入: [[1,5,9],[3,5,7]]

期望: 1

t=5 两路同时心跳,原子地把 cum_a 与 cum_b 都加 1,diff 不变;序列 +1, 0, 0, -1, 0;只有 1 次从 +1 经 0 到 -1 的反号。

Case 14 · typical: single-element-each-different-times

输入: [[1],[2]]

期望: 0

t=1 时 (1, 0),diff=+1;t=2 时 (1, 1),diff=0;只有一个非零符号 +1,从未发生反号,0 次交换。

Case 15 · typical: single-element-each-same-time

输入: [[5],[5]]

期望: 0

t=5 时两路同时 +1,diff 直接为 0,未出现任何非零符号,0 次交换。

Case 16 · boundary: all-cross-feed-ties-throughout

输入: [[1,2,3,4,5,6,7,8,9,10],[1,2,3,4,5,6,7,8,9,10]]

期望: 0

完全相同的两路。每个时刻原子地各自 +1,diff 恒为 0,0 次交换(与 identical-streams 同构但更长)。

最近提交

还没有提交记录。

编码区

实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。

加载编辑器...
计时0:00

默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。

Case 1 · statement-example: alternating with three exchanges

输入: [[1,4,5,8],[2,3,6,7]]

期望: 3

题面例题:合并时间线 1,2,3,4,5,6,7,8,diff 序列为 +1,0,-1,0,+1,0,-1,0;非零符号链 +1 -> -1 -> +1 -> -1 共 3 次严格反号,故答案为 3。

Case 2 · visible: both feeds empty -> 0

输入: [[],[]]

期望: 0

两侧均为空,diff 恒为 0,没有任何符号反转,返回 0。

Case 3 · visible: ts_a empty -> 0

输入: [[],[1,2,3,4,5]]

期望: 0

ts_a 为空时 cum_a 恒为 0,diff = -cum_b 永远 <= 0,从未变成正号,故没有从负到正的反转,返回 0。

Case 4 · visible: ts_b empty -> 0

输入: [[10,20,30],[]]

期望: 0

ts_b 为空时 cum_b 恒为 0,diff = cum_a 永远 >= 0,从未变成负号,故没有正到负的反转,返回 0。

Case 5 · visible: identical streams -> 0

输入: [[1,2,3,4,5],[1,2,3,4,5]]

期望: 0

两路完全相同时,每个时刻原子地各自 +1,diff 始终为 0,从未达到非零符号,故 0 次交换。

Case 6 · typical: a-leads-then-b-overtakes

输入: [[1,2,3],[10,11,12,13]]

期望: 1

t=1..3 时 cum_a 一路领先 (diff = +1, +2, +3);t=10..12 cum_b 追平到 0;t=13 cum_b 超出,diff = -1,从 +1 严格反号,唯一一次交换。

Case 7 · typical: a-leads-but-b-never-catches-up

输入: [[1,2,3,4],[10,11]]

期望: 0

cum_a 全程领先,最终 cum_b 仍未追上 cum_a,diff 始终 > 0,无符号反转,返回 0。

Case 8 · typical: b-leads-but-a-never-catches-up

输入: [[10,11],[1,2,3,4]]

期望: 0

cum_b 全程领先,最终 cum_a 仍未追上,diff 始终 < 0,无符号反转,返回 0。

Case 9 · typical: zero-pass-through-counts-as-one

输入: [[1,2,3],[4,5,6,7,8]]

期望: 1

diff 走 +1,+2,+3,+2,+1,0,-1,-2;从最后一次非零符号 +1 经过 0 后变为 -1,整段塌缩为 1 次严格反号交换。

Case 10 · typical: alternating-a-leads-shared-tie-instants

输入: [[1,3,5,7],[2,4,6,8]]

期望: 0

A 总是先到,每对相邻时刻 diff 走 +1,0,+1,0,+1,0,+1,0;非零符号始终为 +1,无反号,0 次交换。

Case 11 · typical: same-event-count-but-interleaved-no-flip

输入: [[2,4,6,8],[1,3,5,7]]

期望: 0

B 总是先到一拍,diff 走 -1,0,-1,0,-1,0,-1,0;非零符号始终为 -1,无反号,0 次交换。

Case 12 · typical: cross-flip-twice-with-zero-passes

输入: [[1,2,9,10,11],[3,4,5,6]]

期望: 2

t=1,2 时 A 领先 (diff +1,+2);t=3..6 时 B 追上并反超:diff 走 +1, 0, -1, -2,从 +1 经 0 跌到 -1 计 1 次交换;t=9 (3,4,-1)、t=10 (4,4,0)、t=11 (5,4,+1),从 -1 经 0 升到 +1 又计 1 次交换;共 2 次。

Case 13 · typical: cross-feed-tie-mid-timeline

输入: [[1,5,9],[3,5,7]]

期望: 1

t=5 两路同时心跳,原子地把 cum_a 与 cum_b 都加 1,diff 不变;序列 +1, 0, 0, -1, 0;只有 1 次从 +1 经 0 到 -1 的反号。

Case 14 · typical: single-element-each-different-times

输入: [[1],[2]]

期望: 0

t=1 时 (1, 0),diff=+1;t=2 时 (1, 1),diff=0;只有一个非零符号 +1,从未发生反号,0 次交换。

Case 15 · typical: single-element-each-same-time

输入: [[5],[5]]

期望: 0

t=5 时两路同时 +1,diff 直接为 0,未出现任何非零符号,0 次交换。

Case 16 · boundary: all-cross-feed-ties-throughout

输入: [[1,2,3,4,5,6,7,8,9,10],[1,2,3,4,5,6,7,8,9,10]]

期望: 0

完全相同的两路。每个时刻原子地各自 +1,diff 恒为 0,0 次交换(与 identical-streams 同构但更长)。