题目来源
题目描述
题目解析
关键是两个单词不能含有相同的字母,那么,怎么判断两个单词不含有相同的字母呢?
暴力
方法1:暴力枚举
class Solution {
int product(std::string &word1, std::string &word2){
int ans = 0;
std::vector<int> vec(26);
for(auto ch : word1){
++vec[ch - 'a'];
}
for(auto ch : word2){
if(vec[ch - 'a'] > 0){
return 0;
}
}
return word1.size() * word2.size();
}
public:
int maxProduct(vector<string>& words) {
int ans = 0, len = words.size();
std::string word1, word2;
for (int i = 0; i < len; ++i) {
word1 = words[i];
for (int j = i + 1; j < len; ++j) {
word2 = words[j];
if(word1.size() * word2.size() > ans){
ans = std::max(ans, product(word1, word2));
}
}
}
return ans;
}
};
怎么优化呢?
- 观察上面,可以看到每一次都要重复判断是不是有重复字符。
- 我们可以使用位运算预处理每个单词。
位运算
通过位运算操作判断两个单词是否有公共字母。
- 由于单词只包含小写字母,共有26个小写字母,因此可以使用位掩码的最低26位分别表示每个字母是否在这个单词中出现。
- 我们可以将单词中的每个字母都映射到一个 int 类型的不同位上,这样,就做到了每个单词都对应一个 int 类型的数值
- 这样的话,我们对比两个单词是否包含相同的字母,只需要把它们对应的 int 数值做 & 运算,看是不是等于 0 即可,如果等于 0 ,说明没有相同的位是 1,也就不存在相同的字母。
class Solution {
int convert(std::string &word){
int ans = 0, len = word.size();
for (int i = 0; i < len; ++i) {
//expr1<<expr2表示expr1在计算机内部转换而成的二进制数字串左移expr2位
ans |= ( 1 << (word[i] - 'a'));
}
return ans;
}
public:
int maxProduct(vector<string>& words) {
int n = words.size();
std::vector<int> bitset(n);
for (int i = 0; i < n; ++i) {
bitset[i] = convert(words[i]);
}
int maxProd = 0;
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
if((bitset[i]&bitset[j] )== 0){
maxProd = max(maxProd, int(words[i].size() * words[j].size()));
}
}
}
return maxProd;
}
};