题目重点:每个 query 给起始下标,求 nums[index:] 中数值最大的元素出现多少次;只需维护当前最大值和计数。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- query index 采用 0-based 且必须在 [0,n);非法索引训练代码报错。
- 后缀包含该下标及末尾;返回每个 query 对应次数,保留 query 原顺序。
- 数值可负;目标是‘数值最大者的出现次数’,不是‘出现频率最高的数的频率’。
解题路线
- 从右向左扫,维护当前 suffix 的最大数 largest 和该数出现次数 count。
- 新值大于 largest 时,最大值换成新值且 count=1;等于 largest 时 count+1;小于 largest 时 count 不变。
- 每个位置 i 保存 count[i]。回答 query 只读 count[index],可重复和乱序查询。
- 若只给一个 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],线段树节点应保存什么合并信息?
- 若要返回最大值本身及其下标列表,输出成本怎样计算?
