← 返回题目列表

最大单词长度乘积如何用位掩码判断两个单词是否无公共字母?

中等 第 23 / 26 题 更新于 2026/08/01
位运算位掩码字符串集合判断

简化版

每个单词可以用 26 位 bitmask 表示包含哪些小写字母。两个单词没有公共字母,当且仅当 (mask1 & mask2) == 0。枚举单词对,满足无交集时更新长度乘积最大值。

详细版

构建单词 mask 时,字符 c 对应第 c-'a' 位。一个单词里某个字母出现多次也只会让对应位为 1,不影响集合表示。预处理所有单词 mask 后,双层枚举单词对,用按位与快速判断字母集合是否相交。

时间复杂度 O(totalChars + n^2),空间复杂度 O(n)。优化点是相同 mask 只保留最大单词长度,可以减少比较次数。

完整版教学

一、为什么字母集合适合用 bitmask

题目只涉及 26 个小写字母,每个字母只有“出现/未出现”两种状态。用 26 位整数表示集合非常自然。

a -> 第 0 位
b -> 第 1 位
z -> 第 25 位

例如单词 "abca" 的集合其实是 {a,b,c},mask 低三位为 1。

二、如何构建单词 mask

遍历单词中的每个字符 c

mask |= 1 << (c - 'a')

|= 会把对应位设置为 1。即使同一个字母出现多次,也不会改变结果。

单词字母集合mask 直观表示
abc{a,b,c}低 3 位为 1
foo{f,o}f 和 o 对应位为 1

记忆钩子:用 bitmask 表示集合时,重复元素天然被去重。

三、为什么按位与能判断是否有公共字母

如果两个单词某个字母都出现,那么它们的 mask 在对应位都是 1。按位与后,这一位仍然是 1。

mask1 & mask2 == 0  => 没有任何公共 1 位

例如:

abc: 00111
de : 11000
&   00000  => 无公共字母

这比用 HashSet 逐字符判断更紧凑。

四、代码模板

int maxProduct(String[] words) {
    int n = words.length;
    int[] masks = new int[n];
    for (int i = 0; i < n; i++) {
        int mask = 0;
        for (char c : words[i].toCharArray()) {
            mask |= 1 << (c - 'a');
        }
        masks[i] = mask;
    }
    int ans = 0;
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            if ((masks[i] & masks[j]) == 0) {
                ans = Math.max(ans, words[i].length() * words[j].length());
            }
        }
    }
    return ans;
}

双层枚举仍然是 O(n^2),但交集判断变成了常数时间。

五、用数字例子推演

words=["abcw","baz","foo","bar","xtfn","abcdef"]

"abcw" mask 包含 a,b,c,w
"xtfn" mask 包含 x,t,f,n
二者按位与为 0
乘积 = 4 * 4 = 16

"abcw""abcdef"a,b,c 公共字母,按位与不为 0,不能作为候选。

六、相同 mask 如何优化

如果多个单词字母集合相同,只需要保留最大长度。因为对外判断交集时,同一个 mask 的表现完全一样,长度越大越有利。

mask -> maxLength
情况是否需要保留多个
相同 mask,不同长度保留最大长度
不同 mask都可能影响答案

这样可以减少后续 pair 数量。

七、常见误区与追问

  • 误区:用异或判断无公共字母。 异或不能判断交集,按位与才是交集。
  • 误区:重复字母导致长度计算错误。 mask 只用于集合判断,乘积仍用原单词长度。
  • 误区:字符位移没有括号。 1 << c - 'a' 可读性差,推荐写 1 << (c-'a')
  • 追问:为什么 int 足够? 26 个小写字母只需要 26 位,int 足够。
  • 追问:如果有大小写或更多字符怎么办? 可能需要 long、BitSet 或多个整数。
  • 追问:复杂度瓶颈在哪? 预处理是字符总数,主要瓶颈是单词对枚举 O(n^2)

八、加强记忆

最大单词长度乘积的关键是把“字母集合是否相交”变成 (mask1 & mask2) == 0。每个单词一个 26 位集合,重复字母天然去重;交集为空才计算长度乘积。记住按位与表示集合交集,不要拿异或来判断无公共元素。