Cloud SWE · Onsite Coding / Algorithm

Apple 只给大小计数 Oracle 怎么找中位数:可解条件在哪里

已知整数取值范围时二分秩;题目未明确值域,任意实数精确中位数不可由有限次计数查询保证。

题目重点:已知整数取值范围时二分秩;题目未明确值域,任意实数精确中位数不可由有限次计数查询保证。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练代码额外假设原值为已知闭区间 [L,R] 内整数,Oracle `count_greater(x)` 精确返回严格大于 x 的元素数。
  • 偶数 N 同时返回下中位数、上中位数和二者平均数;真实接口若只要某一种,需先确认。
  • Oracle 查询成本单独记 Q,不假设内部是 O(1);若输入是任意实数且只给严格比较计数,有限查询通常无法精确恢复未知值。

解题路线

  1. 由 `count_at_most(x)=N−count_greater(x)` 得到前缀秩;对第 k 小值,找最小整数 x 使 count_at_most(x)≥k。
  2. 因为 count_at_most 随 x 非降,二分 [L,R];对 k=(N+1)//2 和 k=(N+2)//2 各查一次,覆盖奇偶长度与重复值。
  3. 若 Oracle 同时返回 less/greater,可算等于 x 的数 `N−less−greater`,用于验证边界与重复元素。
  4. 信息边界:对任意实数,即使做有限次阈值查询,两个不同实数可落在所有查询阈值同一侧而给完全相同回答,因此不能保证精确值;须有整数/离散候选集、精度目标或原值可访问。
  5. 训练代码在 1,715 个短整数多重集上,以排序后的两个中位位置独立对照。

手动走一遍

数组隐藏为 [1,2,2,9],N=4。查 x=2 时 greater=1,故 ≤2 的有 3 个;第 2 小和第 3 小都可二分定位为 2,平均中位数也是 2。若隐藏值是 1.234567... 的未知实数,有限次只问大小计数不能确定全部小数位。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

from collections.abc import Callable


def median_from_count_greater(
    count: int,
    lower_bound: int,
    upper_bound: int,
    count_greater: Callable[[int], int],
) -> tuple[int, int, float]:
    """Integer domain [L,R]; oracle returns number of values strictly > x."""
    if count <= 0 or lower_bound > upper_bound:
        raise ValueError("non-empty data and valid integer bounds required")

    def kth(rank: int) -> int:
        low, high = lower_bound, upper_bound
        while low < high:
            middle = (low + high) // 2
            count_at_most = count - count_greater(middle)
            if count_at_most >= rank:
                high = middle
            else:
                low = middle + 1
        return low

    left = kth((count + 1) // 2)
    right = kth((count + 2) // 2)
    return left, right, (left + right) / 2

复杂度

每个 order statistic 需 O(log(R−L+1)) 次 Oracle 查询,额外 O(1) 空间;总运行时间乘以 Oracle 单次成本。若值域离散但很大、只给候选值列表,可在排序后的候选集合上二分。

易错点与追问

容易失分的边界

  • 把 `greater(x)` 直接当 `≤x` 而没用 N 补集。
  • 有重复值时只凭等于 N/2 的比较计数找位置,跳过一整段相同值。
  • 奇偶中位数口径未签便给唯一数值。
  • 题目未明确值域,却宣称二分任意实数能精确返回中位值。
  • 把 Oracle 查询视为免费的 O(1) 而不问数据规模/实现。

继续深挖

  • 若整数无已知边界,怎样先指数扩张找到包含中位数的区间?
  • 若 Oracle 有误差 ±ε,能给中位数什么保证?
  • 只需 ε 近似的实数中位数时如何选停止条件?
  • 若支持批量阈值查询,怎样减少网络往返?
✓已复制微信号!