LeetCode LCR 005. 最大单词长度乘积
题目描述


题意分析
从字符串数组中选择两个不同下标的单词,要求两者没有任何公共字母,返回它们原始长度乘积的最大值。若没有合法配对,返回零。
所有单词非空且只含小写英文字母。判断能否配对只关心出现过哪些字母,但计算乘积仍要使用完整单词长度,重复字母也占长度,不能把两个含义混为一谈。
解法:字母集合位掩码
核心思路
[!blue]
每个单词会参与多次配对,若每次重新扫描字符判断交集,就会反复构造同一份集合。先把每个单词的字母集合预处理好,再在不同单词间复用。
字符集只有二十六个小写字母,因此一个整数的低二十六位足以记录出现情况。令
mask[i]的第c - 'a'位为一,表示该单词出现过字符c,建表时使用按位或mask[i] |= 1 << (c - 'a')。按位或重复设置同一位不会改变结果,正好对应“出现过即可”;如果改用加法,重复字符会产生进位,破坏其他字母的位置。掩码有意忽略出现次数和顺序,这不会影响两个单词是否有公共字母。
两个掩码按位与后,某位为一恰好表示对应字母在两边都出现。因此
(mask[i] & mask[j]) == 0当且仅当两个单词无公共字母;通过判定后,用两个原长度的乘积更新最大值。每对只需检查一次,内层从
j = i + 1开始,既排除自己与自己配对,也避免反向重复枚举。答案从零开始,没有任何合法配对时自然保持零。
解题步骤
- 创建与单词数等长的掩码数组,初始全部为零。
- 每个单词只扫描一次,将出现字母对应的位用按位或设为一。
- 枚举所有
i < j的单词对,按位与为零才计算原单词长度乘积。- 持续保存最大乘积并返回。
代码实现
class Solution {
public int maxProduct(String[] words) {
int n = words.length;
int[] mask = new int[n];
// 预处理:每个单词的字母集合压进一个 int 的低 26 位,只算一次。
for (int i = 0; i < n; ++i) {
for (char c : words[i].toCharArray()) {
mask[i] |= 1 << (c - 'a');
}
}
int answer = 0;
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
// 按位与为 0 等价于两个字母集合不相交。
if ((mask[i] & mask[j]) == 0) {
answer = Math.max(answer, words[i].length() * words[j].length());
}
}
}
return answer;
}
}
func maxProduct(words []string) (answer int) {
n := len(words)
mask := make([]int, n)
// 预处理:每个单词的字母集合压进一个整数的低 26 位,只算一次。
for i, w := range words {
for _, c := range w {
mask[i] |= 1 << (c - 'a')
}
}
for i, x := range mask {
for j := i + 1; j < n; j++ {
// 按位与为 0 等价于两个字母集合不相交。
if x&mask[j] == 0 {
answer = max(answer, len(words[i])*len(words[j]))
}
}
}
return
}
复杂度分析
设
n为单词数,S为全部单词字符总数,Lmax为最长单词长度。
- 时间复杂度:$O(S + n^2)$,预处理每个字符一次,配对阶段每对仅做常数次位运算和长度计算。
- 空间复杂度:掩码表占 $O(n)$。Java 代码在处理单词时调用
toCharArray(),峰值还需要 $O(Lmax)$ 的临时字符数组,因此额外空间为 $O(n + Lmax)$;Go 的当前实现为 $O(n)$。
关键点总结
[!green]
- 掩码表示字母是否出现,原单词长度表示总字符数,两者分别用于合法性和得分。
- 有限的二十六字母集合可以放入整数的低二十六位,按位与直接表示集合交集。
- 预处理将单词集合从重复计算变为一次构造、多次使用。
- 置位使用按位或,重复字符不会改变集合。
易错点总结
[!yellow]
- 用加法累积字母标记,重复字母会使位产生进位。
- Java 中应写完整括号
(mask[i] & mask[j]) == 0,避免位与和比较的优先级混淆。- 乘积使用原单词长度,不能用掩码里一的数量代替。
- 两个单词只要有一个公共字母就不合法,不需要整个掩码相同。
- 这份单整数掩码依赖小写英文字母范围,不能不改表示就套到任意字符集。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 1178. 猜字谜 | 困难 | 同样用字母位掩码表示出现集合,原题按谜面子集匹配,本题用按位与为0判断不相交。 |
| 1239. 串联字符串的最大长度 | 中等 | 同样要求字符集合不重叠,原题可选多个串,需要在选择过程中合并掩码。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!