SWE Intern · OA Coding

Rippling OA Consistent Logs:全局最小频次与最长合法滑窗

先求全数组中各不同值的最小正频次 k,再找窗口最高频次恰为 k 的最大长度;用超限计数维护 O(n) 窗口。

题目重点:先求全数组中各不同值的最小正频次 k,再找窗口最高频次恰为 k 的最大长度;用超限计数维护 O(n) 窗口。

题意与假设

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

  • 训练版输入整数数组,空数组返回 0;只对整数组中实际出现过的元素求 minFreq,不能把未出现元素频率 0 算进去。
  • 候选窗口必须连续,条件是窗口中最大频次**等于**全局 k,不是窗口最小频次、不同元素数或某特定元素频次。

解题路线

  1. 先用 Counter 得每个不同值的全局频次,取最小 k。滑窗维护局部计数,右端加入新值后,之前所有计数≤k,只有新值可能超过 k;因此 while 该新值计数>k 时右移左端并减其计数。
  2. 每步窗口满足所有值出现次数≤k,记录最大长度。为何可用‘≤k’求原题的‘=k’:若全局最长合法≤k窗口的最高频次<k,且它不是整数组,就能向相邻一侧扩一格仍不超 k,矛盾;整数组则各元素频次至少 k,故也不可能全<k。
  3. 每个左右指针至多移动 n 次,初始计数 O(n),整体 O(n);不必在左端缩小时维护可能下降的 `mode frequency`,避免陈旧最大频次。
  4. 对所有长度≤8、值域 0..2 的 9,841 个数组,用 O(n²) 枚举每个子数组的 Counter 精确核对。

手动走一遍

数组 [1,1,1,2,2] 的全局频次为 3 与 2,k=2。窗口 [1,1,2,2] 中两值最高频次均 2,长度 4;整个数组的 1 出现 3 次不合法。

Python 参考实现

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

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

from collections import Counter, defaultdict


def longest_consistent_subarray(values: list[int]) -> int:
    """Max length with window max frequency = global min positive frequency."""
    if not values:
        return 0
    threshold = min(Counter(values).values())
    counts: dict[int, int] = defaultdict(int)
    left = best = 0
    for right, value in enumerate(values):
        counts[value] += 1
        while counts[value] > threshold:
            counts[values[left]] -= 1
            left += 1
        best = max(best, right - left + 1)
    return best

复杂度

Counter 和滑窗各 O(n) 时间;两张计数表空间 O(U),U 为不同元素数。若数据是无限流,全局 minFreq 尚未确定,不能直接在线使用这套方法。

易错点与追问

容易失分的边界

  • 把 k 算成当前窗口的最小频次而非整数组最小频次。
  • 窗口缩小时依赖陈旧的 maxFreq,不再反映当前值计数。
  • 满足≤k 的窗口一律不检查原题等号却没有论证最大窗口为何可取等号。
  • 把子数组理解为非连续子序列。
  • 忽略空数组无法取全局 minFreq。

继续深挖

  • 如果目标改为窗口最高频次至少 k,还能用同一滑窗吗?
  • 若 minFreq 随流到达会改变,能否在线维护答案?
  • 若值域很大但元素少,内存怎样估?
  • 为什么只需检查刚加入的值是否超限?
✓已复制微信号!