这个题目,果不其然,咱就直接暴力破解加剪枝,比对两个单词是是否有相同字母。时间复杂度就O(n*n*wordlength*wordlength)大概这么多吧,确实有点多。上代码了:
int maxProduct(vector<string>& words) {
int max = 0;
int flag;
//从单词长度最长的开始两两比对
for(int i=words.size() - 1;i > 0; i--){
for(int j = i - 1;j >= 0; j--){
int t = words[i].length() * words[j].length();
if(t <= max){
continue;
}
flag = 1;
for(int m = 0;m < words[i].length();m++){
for(int n = 0;n < words[j].length();n++){
if(words[i][m] == words[j][n]){
flag = 0;
break;
}
}//当两个单词有相同的字母时,就这两个单词就可以停止比对了
if(flag == 0){
break;
}
}
if(flag == 1){
max = t>max?t:max;
}
}
}
return max;
}
然后再看看官方题解:如果可以将判断两个单词是否有公共字母的时间复杂度降低到 O(1),则可以将总时间复杂度降低到 O(n^2)。可以使用位运算预处理每个单词,通过位运算操作判断两个单词是否有公共字母。由于单词只包含小写字母,共有 26个小写字母,因此可以使用位掩码的最低 26位分别表示每个字母是否在这个单词中出现。将 a 到 z 分别记为第 0 个字母到第 25 个字母,则位掩码的从低到高的第 i位是 1 当且仅当第 i个字母在这个单词中。
用数组masks 记录每个单词的位掩码表示。计算数组 \textit{masks}masks 之后,判断第 i个单词和第 j 个单词是否有公共字母可以通过判断 masks[i] & masks[j] 是否等于 0 实现,当且仅当masks[i] & masks[j]=0 时第 i个单词和第 j 个单词没有公共字母,此时使用这两个单词的长度乘积更新单词长度的最大乘积。
class Solution {
public:
int maxProduct(vector<string>& words) {
int length = words.size();
vector<int> masks(length);
for (int i = 0; i < length; i++) {
string word = words[i];
int wordLength = word.size();
for (int j = 0; j < wordLength; j++) {
masks[i] |= 1 << (word[j] - 'a');
}
}
int maxProd = 0;
for (int i = 0; i < length; i++) {
for (int j = i + 1; j < length; j++) {
if ((masks[i] & masks[j]) == 0) {
maxProd = max(maxProd, int(words[i].size() * words[j].size()));
}
}
}
return maxProd;
}
};
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/aseY1I/solution/dan-ci-chang-du-de-zui-da-cheng-ji-by-le-l5mu/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
浙公网安备 33010602011771号