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

题意分析
选择两个没有任何公共字母的单词,返回它们长度乘积的最大值;不存在合法单词对时返回
0。单词本身允许重复字母,计算长度时也包含这些重复位置。判断两个单词是否兼容,只需要知道各自出现过哪些字母,不关心字母顺序和出现次数。题目只有
26种小写字母,可以把这个出现集合压缩到一个整数中。
解法:位掩码枚举单词对
核心思路
[!blue]
用整数的第
0到第25位分别表示字母a到z。扫描单词中的字符c,用1 << (c - 'a')得到对应位,再通过按位或把它设为1。同一字母出现多次仍只设置同一个位,不会影响其他字母。两个掩码按位与时,只有双方都为
1的位置才会保留下来。因此(mask[i] & mask[j]) == 0等价于没有公共字母,可以在常数时间判断一对单词是否合法。预处理好每个单词的掩码和原始长度后,枚举所有
i < j的单词对。合法时用两个原始长度相乘更新最大值,确保既不遗漏任何候选,也不把同一对重复处理。答案初始为0,无合法配对时自然返回零。
解题步骤
- 为每个单词建立掩码,逐字符按位或置位,并记录该单词的完整长度。
- 枚举第一个单词下标
i,再枚举从i + 1开始的第二个下标j。- 若两个掩码按位与为零,计算
lengths[i] * lengths[j],更新答案。- 返回所有合法单词对中的最大长度乘积。
代码实现
class Solution {
// 两个单词没有公共字母,等价于它们的位掩码按位与结果为 0。
public int maxProduct(String[] words) {
int n = words.length;
int[] mask = new int[n];
int[] lengths = new int[n];
for (int i = 0; i < n; i++) {
int bitMask = 0;
for (int j = 0; j < words[i].length(); j++) {
// 重复字母仍用或置位,不累计到其他位
bitMask |= 1 << (words[i].charAt(j) - 'a');
}
mask[i] = bitMask;
// 保存原词长度,不能用不同字母数量替代
lengths[i] = words[i].length();
}
int answer = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if ((mask[i] & mask[j]) == 0) {
answer = Math.max(answer, lengths[i] * lengths[j]);
}
}
}
return answer;
}
}
func maxProduct(words []string) int {
// 两个单词没有公共字母,等价于它们的位掩码按位与结果为 0。
n := len(words)
mask := make([]int, n)
lengths := make([]int, n)
for i, word := range words {
bitMask := 0
for j := 0; j < len(word); j++ {
// 重复字母仍用或置位,不累计到其他位
bitMask |= 1 << (word[j] - 'a')
}
mask[i] = bitMask
// 保存原词长度,不能用不同字母数量替代
lengths[i] = len(word)
}
answer := 0
for i := 0; i < n; i++ {
for j := i + 1; j < n; j++ {
if mask[i]&mask[j] == 0 {
product := lengths[i] * lengths[j]
if product > answer {
answer = product
}
}
}
}
return answer
}
复杂度分析
- 时间复杂度:$O(S+n^2)$,
S为总字符数,预处理后每对常数判断。- 空间复杂度:$O(n)$,掩码与长度数组。
关键点总结
[!green]
- 位掩码保存的是字母出现集合,按位与直接判断集合是否相交。
- 预处理只扫描每个字符一次,之后每次配对都不需要重新遍历单词。
- 掩码负责判断合法性,原始词长负责计算收益,两者不能互相替代。
易错点总结
[!yellow]
- 置位使用按位或,不能用加法,否则重复字母可能产生进位,错误改变其他字母位。
- 掩码中
1的数量是不同字母数,不是单词长度,不能拿它计算乘积。- 判断条件是按位与为零,不是两个掩码不相等;不同字母集合仍可能含有公共字母。
- 只枚举两个不同下标,并在没有合法单词对时保留答案
0。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 1178. 猜字谜 | 困难 | 同样用字母位掩码表示出现集合,原题按谜面子集匹配,本题用按位与为0判断不相交。 |
| 1239. 串联字符串的最大长度 | 中等 | 同样要求字符集合不重叠,原题可选多个串,需要在选择过程中合并掩码。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!