前情提要,在解决lc318的时候,也就是下题
给你一个字符串数组 words
,找出并返回 length(words[i]) * length(words[j])
的最大值,并且这两个单词不含有公共字母。如果不存在这样的两个单词,返回 0
。
示例 1:
输入: words = ["abcw","baz","foo","bar","xtfn","abcdef"]
输出: 16
解释 : 这两个单词为 "abcw", "xtfn"。
示例 2:
输入: words = ["a","ab","abc","d","cd","bcd","abcd"]
输出: 4
解释 : 这两个单词为 "ab", "cd"。
示例 3:
输入: words = ["a","aa","aaa","aaaa"]
输出: 0
解释 : 不存在这样的两个单词。
我的一开始的代码如下
class Solution {
public:
int maxProduct(vector<string>& words) {
int n=words.size();
int ans=0;
for(int i=0;i<n;i++){
int muti=0;
for(int j=i+1;j<n;j++){
bool hascommonChar=false;
for(int x=0;x<words[i].size();x++){
if(words[j].find(words[i][x])!=string::npos){
hascommonChar=true;
break;
}
}
if(!hascommonChar){
muti=words[i].size()*words[j].size();
ans=max(ans,muti);
}
}
}
return ans;
}
};
但是在最后一个案例的时候过不了,原因是时间复杂度过高,出现re了。
然后官方解答使用了位运算
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;
}
};
具体来说,(word[j] - 'a')
可以将小写字母 a~z 转化为 0 ~25 的整数。然后 1 << (word[j] - 'a')
将 1 左移该整数位数的二进制位,得到一个只有该位置为 1,其余位均为 0 的二进制数,表示当前字母在单词中出现的情况。
将多个这样的二进制数通过按位或运算 |=
合并,就可以得到一个长度为 26 的二进制数,表示该单词中所有出现过的字母。将这个二进制数存储在 masks 数组中,就可以用来判断两个单词是否有相同的字母了。
举个例子,对于单词 "ab"
,其对应的位向量二进制数为 0011(表示第 0 和 1 位二进制位上都为 1)。对于单词 "ac"
,其对应的位向量二进制数为 0101(表示第 0 和 2 位二进制位上都为 1)。这两个单词的位向量进行按位与运算,结果是 0001,表示它们存在相同的字母。如果按位与结果为 0,就说明它们没有相同的字母。
再举个例子
对于"az"这个字符串,我们需要将每个字符转换为对应的二进制位,并进行位运算。
首先,根据ASCII码表,字符'a'对应的ASCII码是97,字符'z'对应的ASCII码是122。然后,我们将这些字符的ASCII码减去字符'a'的ASCII码(97),得到它们相对于'a'的偏移量。
对于字符'a': 偏移量 = 97 - 97 = 0 二进制表示 = 00000000
对于字符'z': 偏移量 = 122 - 97 = 25 二进制表示 = 00011001
接下来,我们将偏移量转换为二进制数,并使用位运算符"|"将它们进行按位或运算。
运算结果 = 00000000 | 00011001 = 00011001
所以,对于字符串"az",进行位运算之后得到的结果是00011001。