题目来源:LeetCode318:最大单词长度乘积
问题抽象: 给定一个字符串数组 words(元素为仅包含小写字母的单词),要求计算数组中 任意两个不同单词的长度乘积的最大值,且这两个单词 不包含公共字母(即字母集合无交集),满足以下核心需求:
-
乘积规则定义:
- 长度乘积:两个单词
words[i]和words[j]的长度乘积为len(words[i]) × len(words[j]); - 无公共字母:两个单词的字符集交集为空(如
"abc"与"def"无公共字母,但与"cde"有公共字母'c')。
- 长度乘积:两个单词
-
计算目标:
- 返回满足条件的最大乘积值(整数);
- 若数组中不存在任何一对无公共字母的单词,返回
0。
-
输入约束:
- 数组长度
2 ≤ len(words) ≤ 1000,单词长度1 ≤ len(words[i]) ≤ 1000; - 时间复杂度 O(n²) 或优化至 O(n + m²)(
m为字符集组合数); - 空间复杂度 O(n)(存储单词的字符位掩码)。
- 数组长度
-
边界处理:
- 无解情况:如所有单词均含公共字母(如
["a","aa","aaa"])→ 输出0; - 大长度单词:如
words=["ab","cdefghij"]→ 乘积2×9=18; - 全相同字符:如
words=["x","xx"]→ 有公共字母'x'→ 输出0; - 大规模输入:需避免暴力法
O(n²×L)(L为单词长度)。
- 无解情况:如所有单词均含公共字母(如
输入:字符串数组 words
输出:最大乘积值(整数 ≥0)。
解题思路
核心思路:使用位掩码优化公共字母判断
-
位掩码表示字母集合:
- 每个单词的字母集合可以用一个 32 位整数(掩码)表示。
- 掩码的第
k位为 1 表示字母'a' + k在单词中出现。 - 例如:单词
"ab"的掩码为(1 << 0) | (1 << 1) = 3(二进制...00011)。
-
预处理掩码和最大长度:
- 遍历每个单词,计算其掩码。
- 使用
HashMap记录每个掩码对应的最大单词长度(相同掩码取最长单词)。
-
查找无公共字母的单词对:
- 将
HashMap的键(掩码)转为数组。 - 双重循环遍历所有掩码对(避免重复,内层从
i+1开始)。 - 若两个掩码按位与为 0,说明无公共字母,计算长度乘积并更新最大值。
- 将
-
复杂度分析:
- 时间复杂度:O(n² + L),其中
n为单词数量,L为所有单词总长度。 - 空间复杂度:O(n),用于存储掩码和最大长度。
- 时间复杂度:O(n² + L),其中
代码实现(Java版)🔥点击下载源码
class Solution {
public int maxProduct(String[] words) {
// 记录每个掩码对应的最大单词长度
Map<Integer, Integer> maskToMaxLen = new HashMap<>();
for (String word : words) {
int mask = 0;
// 计算当前单词的掩码
for (int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
mask |= 1 << (c - 'a'); // 设置对应字母的位
}
// 更新该掩码的最大长度
int currentLength = word.length();
int existingLength = maskToMaxLen.getOrDefault(mask, 0);
if (currentLength > existingLength) {
maskToMaxLen.put(mask, currentLength);
}
}
// 少于两个掩码时直接返回0
if (maskToMaxLen.size() < 2) {
return 0;
}
// 将掩码集合转为数组
Integer[] masks = maskToMaxLen.keySet().toArray(new Integer[0]);
int maxProduct = 0;
int numMasks = masks.length;
// 遍历所有掩码对
for (int i = 0; i < numMasks; i++) {
for (int j = i + 1; j < numMasks; j++) {
// 无公共字母时计算乘积
if ((masks[i] & masks[j]) == 0) {
int product = maskToMaxLen.get(masks[i]) * maskToMaxLen.get(masks[j]);
if (product > maxProduct) {
maxProduct = product;
}
}
}
}
return maxProduct;
}
}
代码说明
- 掩码计算:
- 遍历每个字符,将
1 << (c - 'a')按位或到掩码上,记录字母出现情况。
- 遍历每个字符,将
- 长度优化:
- 使用
HashMap确保相同掩码只保留最长单词长度,避免冗余计算。
- 使用
- 掩码对比较:
- 将掩码转为数组后双重循环,内层从
i+1开始避免重复。 - 按位与为 0 表示无公共字母,更新最大乘积。
- 将掩码转为数组后双重循环,内层从
- 边界处理:
- 掩码数量不足 2 时直接返回 0,确保无解时正确。
提交详情(执行用时、内存消耗)

805

被折叠的 条评论
为什么被折叠?



