等长有序数组求第k小:抛弃哨兵的极简二分,对标LeetCode#4通用分割解法

6 阅读2分钟

一、前言

LeetCode第4题「寻找两个有序数组中位数」是经典算法题,全网教程、题解清一色围绕两个任意长度(m≠n)数组实现通用分割二分,依赖正负无穷哨兵值、大量边界if判断。 但在数据库归并Join、磁盘外排序、多传感器时序统计等真实工程场景中,业务常主动把有序数据集切分为长度完全相等的两段,通用二分在等长场景存在代码冗余、分支过多、极值溢出隐患。本文针对两数组等长L、1≤k≤L的限定场景,自研一套无哨兵、无边界特判的迭代二分算法,从不变量层面对比传统通用解法优劣。
#include #include using namespace std; template //约束:v1、v2长度均为L,1 ≤ k ≤ L T find_kth(const vector& v1, const vector& v2, int L, int k) { int f1 = 0, e1 = k - 1; int f2 = 0, e2 = k - 1; int len = k; while (len > 1) { int p1 = (f1 + e1) / 2; int p2 = (f2 + e2) / 2; if (v1[p1] > v2[p2]) { e1 = p1; f2 = len % 2 ? p2 : p2 + 1; } else if (v1[p1] < v2[p2]) { f1 = len % 2 ? p1 : p1 + 1; e2 = p2; } else return v1[p1]; len = e1 - f1 + 1; } return min(v1[f1], v2[f2]); }
落地应用场景

1. 数据库Merge-Join:分库分表后两张分片数据等长有序,归并关联时频繁求分位数/中位数,替换通用二分降低内核计算开销; ​ 2. 外排序多路归并:磁盘拆分后的有序块人工切分为等长数据,两两归并筛选第k元素; ​ 3. 物联网时序数据:多传感器同频率采样,数据点数一致,批量统计分位数; ​ 4. 算法竞赛:题目给定等长有序数组场景,卡常数时优于通用写法。