MAI / SWE · Onsite Coding

Microsoft MAI 后缀最大数出现次数:从右向左一次预处理

每个 query 给起始下标,求 nums[index:] 中数值最大的元素出现多少次;只需维护当前最大值和计数。

题目重点:每个 query 给起始下标,求 nums[index:] 中数值最大的元素出现多少次;只需维护当前最大值和计数。

题意与假设

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

  • query index 采用 0-based 且必须在 [0,n);非法索引训练代码报错。
  • 后缀包含该下标及末尾;返回每个 query 对应次数,保留 query 原顺序。
  • 数值可负;目标是‘数值最大者的出现次数’,不是‘出现频率最高的数的频率’。

解题路线

  1. 从右向左扫,维护当前 suffix 的最大数 largest 和该数出现次数 count。
  2. 新值大于 largest 时,最大值换成新值且 count=1;等于 largest 时 count+1;小于 largest 时 count 不变。
  3. 每个位置 i 保存 count[i]。回答 query 只读 count[index],可重复和乱序查询。
  4. 若只给一个 query,可从该 index 到末尾扫描 O(n−index);多查询时一次后缀预处理 O(n) 更合适。

手动走一遍

[7,5,7,2,7] 从右向左:最后 7→1;2 不变→1;7→2;5 不变→2;最左 7→3,于是 [3,2,2,1,1]。若用‘最高频数’理解,在 [9,1,1] 的整段会错算 2;真正最大值 9 的次数为 1。

Python 参考实现

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

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

from collections.abc import Sequence


def suffix_maximum_counts(nums: Sequence[int], queries: Sequence[int]) -> list[int]:
    """For each index, count occurrences of the numeric maximum of that suffix."""
    n = len(nums)
    counts = [0] * n
    largest = None
    occurrences = 0
    for i in range(n - 1, -1, -1):
        value = nums[i]
        if largest is None or value > largest:
            largest = value
            occurrences = 1
        elif value == largest:
            occurrences += 1
        counts[i] = occurrences
    if any(index < 0 or index >= n for index in queries):
        raise IndexError('query index outside nums')
    return [counts[index] for index in queries]


if __name__ == '__main__':
    assert suffix_maximum_counts([7, 5, 7, 2, 7], [0, 1, 2, 3, 4]) == [3, 2, 2, 1, 1]

复杂度

预处理 O(n) 时间、O(n) 结果数组;q 个查询 O(q) 时间与 O(q) 输出空间。若可以原地覆盖另一个结果缓冲,工作空间仍由 n 个后缀答案决定;只答一个查询可 O(1) 工作空间。

易错点与追问

容易失分的边界

  • 把最大频率当最大数值的频率。
  • 遇更大的数时只加一而不重置计数。
  • 每个 query 重新扫到末尾,最坏 O(nq)。
  • 误用堆并为每个后缀建堆,增加不必要的复杂度。
  • 把 query 下标当 1-based。

继续深挖

  • 若 nums 会更新,如何支持区间最大值及其出现次数的动态查询?
  • 如果 query 是任意 [l,r],线段树节点应保存什么合并信息?
  • 若要返回最大值本身及其下标列表,输出成本怎样计算?
✓已复制微信号!