撮合队列优先级排序(买卖两侧分别排队)
Order Queue Priority
开始编码撮合引擎每次撮合前,都要把当下所有挂单按各自侧的优先级排成一条队列:买盘里愿意出更高价的客户先成交,卖盘里愿意接受更低价的客户先成交,价格打平时先挂出的优先(FIFO)。这就是经典的 price-time priority 队列规则——每一家正经的限价订单簿都长这样。
请实现 solution(orders: list[dict]) -> dict:把输入里所有订单按 side 分流到两条队列,每条队列按本侧的 price-time priority 排好,然后整体打包返回。每条 orders[i] 至少可能带 order_id (str)、side (str)、price (float)、time (int),也可能带 qty 等额外字段。处理口径如下:
- 过滤。
side必须严格等于字面量"buy"或"sell"(小写、不做lower(),不接受"BUY"/"b"/None);price必须存在、非 None 且> 0;time必须存在且非 None;order_id必须存在、非 None 且strip()后非空。任一不满足则整条订单丢弃。原始 dict 不修改、不剥空白、不重新构造——直接进结果。 - 排序。
- **买盘 (
side == "buy")**:先按price降序——出价高者先排队;价相等按time升序——先挂的优先;仍相等按order_id字典序升序——保证相同输入返回顺序确定。 - **卖盘 (
side == "sell")**:先按price升序——要价低者先排队;价相等按time升序;仍相等按order_id字典序升序。
- 打包。返回
{"buys": [<order>, ...], "sells": [<order>, ...]},每个<order>是输入里那条原始 dict 引用(含qty等所有额外字段)。
举例:solution([{"order_id": "A", "side": "buy", "price": 100.5, "time": 1000, "qty": 10}, {"order_id": "B", "side": "buy", "price": 100.5, "time": 999, "qty": 5}, {"order_id": "C", "side": "sell", "price": 101.0, "time": 1001, "qty": 8}, {"order_id": "D", "side": "sell", "price": 100.8, "time": 1005, "qty": 12}]) 应返回 {"buys": [{"order_id": "B", ...}, {"order_id": "A", ...}], "sells": [{"order_id": "D", ...}, {"order_id": "C", ...}]}。买盘里 A 与 B 同价 100.5,B 的 time=999 早于 A 的 time=1000,按 FIFO 先排队;卖盘里 D 的 price=100.8 比 C 的 101.0 低,D 先排队(卖盘出价低者优先)。注意 D 的 time=1005 反而比 C 的 1001 晚——price-time priority 是先看价再看时间,时间不会越过价格。
10000 条订单的体量下,请用 O(N log N) 的方案:一次过滤、两次 sorted 各扫一侧,复杂度对应交易所每个 tick 重排队列的开销就足够了。
约束条件
- 0 ≤ len(orders) ≤ 10000
- 每条订单是 dict,至少可能带 `order_id` (str)、`side` (str)、`price` (float|int)、`time` (int),也可能带 `qty` 等额外字段
- `side` 仅接受字面量小写 `"buy"` 或 `"sell"`;其余值(None、`"BUY"`、`"b"` 等)整条丢弃
- `price` 必须存在、非 None 且 `> 0`;否则整条丢弃
- `time` 必须存在且非 None;否则整条丢弃。允许两条订单 `time` 相等
- `order_id` 必须存在、非 None 且 `str.strip()` 后非空;否则整条丢弃。`order_id` 不做 strip,原样保留进结果
- 返回 `{"buys": list[dict], "sells": list[dict]}`;每个 dict 是输入里那条原始订单(保留所有字段)
- 买盘排序:`price` **降序**;价相等按 `time` **升序**;仍相等按 `order_id` **升序**(字典序)
- 卖盘排序:`price` **升序**;价相等按 `time` **升序**;仍相等按 `order_id` **升序**(字典序)
样例
Case 1 · example from statement (price-time priority on both sides)
输入: [[{"order_id":"A","side":"buy","price":100.5,"time":1000,"qty":10},{"order_id":"B","side":"buy","price":100.5,"time":999,"qty":5},{"order_id":"C","side":"sell","price":101,"time":1001,"qty":8},{"order_id":"D","side":"sell","price":100.8,"time":1005,"qty":12}]]
期望: {"buys":[{"order_id":"B","side":"buy","price":100.5,"time":999,"qty":5},{"order_id":"A","side":"buy","price":100.5,"time":1000,"qty":10}],"sells":[{"order_id":"D","side":"sell","price":100.8,"time":1005,"qty":12},{"order_id":"C","side":"sell","price":101,"time":1001,"qty":8}]}
买盘 A、B 同价 100.5,B 的 time=999 早于 A 的 time=1000,B 先排队。卖盘 D 的 price=100.8 比 C 的 101.0 低,D 先排队——卖盘出价低者优先;注意 D 的 time=1005 实际比 C 的 1001 晚,time 不会越过 price。
Case 2 · multiple price levels and FIFO at same level
输入: [[{"order_id":"B1","side":"buy","price":99,"time":100},{"order_id":"B2","side":"buy","price":100,"time":200},{"order_id":"B3","side":"buy","price":100,"time":150},{"order_id":"B4","side":"buy","price":101,"time":250},{"order_id":"S1","side":"sell","price":102,"time":110},{"order_id":"S2","side":"sell","price":103,"time":120},{"order_id":"S3","side":"sell","price":102,"time":130}]]
期望: {"buys":[{"order_id":"B4","side":"buy","price":101,"time":250},{"order_id":"B3","side":"buy","price":100,"time":150},{"order_id":"B2","side":"buy","price":100,"time":200},{"order_id":"B1","side":"buy","price":99,"time":100}],"sells":[{"order_id":"S1","side":"sell","price":102,"time":110},{"order_id":"S3","side":"sell","price":102,"time":130},{"order_id":"S2","side":"sell","price":103,"time":120}]}
买盘按 price 降序:B4 (101) > B2/B3 (100) > B1 (99);100 这一档里 B3 的 time=150 早于 B2 的 time=200,B3 排在 B2 前面。卖盘按 price 升序:S1/S3 (102) < S2 (103);102 这一档里 S1 的 time=110 早于 S3 的 time=130。
最近提交
还没有提交记录。
编码区
实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
Case 1 · example from statement (price-time priority on both sides)
输入: [[{"order_id":"A","side":"buy","price":100.5,"time":1000,"qty":10},{"order_id":"B","side":"buy","price":100.5,"time":999,"qty":5},{"order_id":"C","side":"sell","price":101,"time":1001,"qty":8},{"order_id":"D","side":"sell","price":100.8,"time":1005,"qty":12}]]
期望: {"buys":[{"order_id":"B","side":"buy","price":100.5,"time":999,"qty":5},{"order_id":"A","side":"buy","price":100.5,"time":1000,"qty":10}],"sells":[{"order_id":"D","side":"sell","price":100.8,"time":1005,"qty":12},{"order_id":"C","side":"sell","price":101,"time":1001,"qty":8}]}
买盘 A、B 同价 100.5,B 的 time=999 早于 A 的 time=1000,B 先排队。卖盘 D 的 price=100.8 比 C 的 101.0 低,D 先排队——卖盘出价低者优先;注意 D 的 time=1005 实际比 C 的 1001 晚,time 不会越过 price。
Case 2 · multiple price levels and FIFO at same level
输入: [[{"order_id":"B1","side":"buy","price":99,"time":100},{"order_id":"B2","side":"buy","price":100,"time":200},{"order_id":"B3","side":"buy","price":100,"time":150},{"order_id":"B4","side":"buy","price":101,"time":250},{"order_id":"S1","side":"sell","price":102,"time":110},{"order_id":"S2","side":"sell","price":103,"time":120},{"order_id":"S3","side":"sell","price":102,"time":130}]]
期望: {"buys":[{"order_id":"B4","side":"buy","price":101,"time":250},{"order_id":"B3","side":"buy","price":100,"time":150},{"order_id":"B2","side":"buy","price":100,"time":200},{"order_id":"B1","side":"buy","price":99,"time":100}],"sells":[{"order_id":"S1","side":"sell","price":102,"time":110},{"order_id":"S3","side":"sell","price":102,"time":130},{"order_id":"S2","side":"sell","price":103,"time":120}]}
买盘按 price 降序:B4 (101) > B2/B3 (100) > B1 (99);100 这一档里 B3 的 time=150 早于 B2 的 time=200,B3 排在 B2 前面。卖盘按 price 升序:S1/S3 (102) < S2 (103);102 这一档里 S1 的 time=110 早于 S3 的 time=130。