CS / SWE · Coding

Bloomberg 最长无重复字符子串:滑动窗口不回退

从 CS 面经的明确题名推导 lastSeen 与左边界更新,验证空串、重复密集和字符集限制。

题目重点:从 CS 面经的明确题名推导 lastSeen 与左边界更新,验证空串、重复密集和字符集限制。

题意与假设

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

  • 训练版返回长度,不返回实际子串;字符以语言字符串迭代单位处理。
  • 若题目按 Unicode grapheme 而非 code point 计字符,需先做分段;题目未说明。

解题路线

  1. 窗口 [left,right] 保证无重复,lastSeen[char] 存该字符最后位置。
  2. 遇重复且 lastSeen≥left 时把 left 跳到 lastSeen+1;否则 left 不变,绝不能向左回退。
  3. 每步更新 lastSeen 与最大窗口长;证明 right 每次+1,left 最多前进 n 次,所以 O(n)。
  4. 用 abba 干跑:最后一个 a 的旧位置在窗口左侧,left 不能从 2 回到 1。

手动走一遍

abba:r=0/1 窗口 ab 长 2;r=2 遇 b,left=2;r=3 遇 a,但旧 a 位置 0<left,窗口 ba 长 2,答案 2。

Python 参考实现

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

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

def longest_unique_length(text):
    left = 0
    last_seen = {}
    answer = 0
    for right, char in enumerate(text):
        if char in last_seen and last_seen[char] >= left:
            left = last_seen[char] + 1
        last_seen[char] = right
        answer = max(answer, right - left + 1)
    return answer

复杂度

O(n) 时间、O(min(n,字符集大小)) lastSeen 空间;若字符集固定且小可用定长数组。

易错点与追问

容易失分的边界

  • left=lastSeen+1 而不取不回退条件。
  • 把子序列当子串。
  • 遇重复就清空整个窗口,导致退化或错误。
  • 忽略字符集限制。

继续深挖

  • 若还要返回最早的最长子串?
  • 流式 chunk 如何维持状态?
  • Unicode grapheme 怎样处理?
✓已复制微信号!