跨源行情累计计数领先权交换次数
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_a 与 ts_b 都是严格升序的整数毫秒时间戳数组。沿合并时间线按时间先后扫描;在每个唯一时刻 t(取自 ts_a ∪ ts_b)原子地更新 cum_a 与 cum_b 为该 feed 中时间戳 <= t 的事件计数,再计算 diff(t) = cum_a(t) - cum_b(t)。「领先权交换」定义为 diff 在两次相邻非零符号之间发生严格反号——途中经过 0 的状态不算一次交换、而算零次(一次「打平」),除非随后下一个非零符号与上一次非零符号相反,那才整体计为一次交换。
边界情形:
- 若
len(ts_a) == 0或len(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_a与cum_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 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
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 同构但更长)。