Member / SWE · VO Coding

Netflix 无共同字符字符串对:Set 判交与 Bitmask 追问

对应 Netflix Member 组 Coding 的 string pair 题,给出 Unicode 通用集合基线与仅小写 a–z 时 26 位掩码优化,分析输出下界。

题目重点:对应 Netflix Member 组 Coding 的 string pair 题,给出 Unicode 通用集合基线与仅小写 a–z 时 26 位掩码优化,分析输出下界。

题意与假设

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

  • 训练版返回原列表下标 pair `(i,j)` 且 i<j;如果题目只要数量,可直接计数不保留输出。
  • 一般版本按 Unicode code point 精确比较、大小写不合并;bitmask 版本仅允许 ASCII 小写 a–z,否则抛错。
  • 空字符串与任意字符串无共同字符;重复字符串位于不同下标,仍是不同输入元素。

解题路线

  1. 先把每个字符串转为字符集合,再枚举所有 i<j,用 set.isdisjoint 检查是否没有交集。这样字符重复不影响结果。
  2. 若确定字母表只有 26 个小写字母,为每串构造 26 位整数,第 c 位标记是否出现;两串按位与为零即无共同字符。先检查输入范围,不能让任意 Unicode 字符直接映射错误位。
  3. U 个不同字符掩码时,可按 mask 聚合相同字符串并计算 pair 数以减少重复比较;但如果必须返回全部 pair,输出可能 Θ(n²),无法普遍规避。

手动走一遍

[ab,cd,bc,""] 中 ab 与 cd 无公共字符,ab 与 bc 共享 b 不合格;空串与另外三串都合格。小写版本 mask(ab)=000...011,mask(cd)=000...1100,按位与为 0。

Python 参考实现

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

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

from itertools import combinations


def pairs_without_shared_characters(words):
    """Return index pairs; Unicode characters are treated as exact code points."""
    letters = [set(word) for word in words]
    return [(left, right) for left, right in combinations(range(len(words)), 2)
            if letters[left].isdisjoint(letters[right])]


def lowercase_bitmask(word):
    mask = 0
    for char in word:
        if not "a" <= char <= "z":
            raise ValueError("bitmask variant requires lowercase ASCII")
        mask |= 1 << (ord(char) - ord("a"))
    return mask


def lowercase_pairs_with_bitmasks(words):
    masks = [lowercase_bitmask(word) for word in words]
    return [(left, right) for left, right in combinations(range(len(words)), 2)
            if masks[left] & masks[right] == 0]

复杂度

预处理所有字符 O(L),L 为总字符数;一般集合两两判断最坏 O(n²A),A 为较小集合大小,额外空间 O(L+P)。26 位掩码版本预处理 O(L)、比较 O(n²) 常数位运算、输出空间 O(P);P 可能 Θ(n²)。

易错点与追问

容易失分的边界

  • 比较字符串本身是否相等,而不是字符集合是否相交。
  • 两个相同字符在一个串内重复出现,误当两串有共同字符。
  • 对大写、数字、中文直接使用 a–z 的位偏移。
  • 只给 pair 数量却声称算法能低于所有输出 pair 的下界。

继续深挖

  • 若字母表有上千字符,可怎样用动态 bitset 或 Roaring bitmap?
  • 只需计数时,按相同 mask 分组能减少多少比较?
  • 字符串总数很大但每串字符很少,倒排索引可如何剪枝?
✓已复制微信号!