VIRTUALS

the virtual labs for the virtuals

0%

LeetCode 318. 最大单词长度乘积

摘要:
位运算记录字符串中字符。

题目

给定一个字符串数组 $words$,找到 $length(word[i]) \times length(word[j])$ 的最大值,并且这两个单词不含有公共字母。你可以认为每个单词只包含小写字母。如果不存在这样的两个单词,返回 $0$。

示例 1:

输入: [“abcw”,”baz”,”foo”,”bar”,”xtfn”,”abcdef”]
输出: 16
解释: 这两个单词为 “abcw”, “xtfn”。

示例 2:

输入: [“a”,”ab”,”abc”,”d”,”cd”,”bcd”,”abcd”]
输出: 4
解释: 这两个单词为 “ab”, “cd”。

示例 3:

输入: [“a”,”aa”,”aaa”,”aaaa”]
输出: 0
解释: 不存在这样的两个单词。


这道题的关键在于判断两个字符串有无公共字符。可以想到的方法有哈希集合,计数数组,以及位运算。

位运算

这道题的字符串中仅有26个字母,可以用位运算方法记录下字符串中出现的字符。
对于一个字符,我们计算出它和 a 的偏移,将 1 左移这个偏移量,那么得到的二进制数就记录下了当前字符。那么,如何记录整个字符串的所有字符呢?
维护一个二进制数 s , 对于字符串中的每一个字符,用上述方法计算出对应的二进制数后,与 s 进行或运算,将每个字符相对 a 的偏移量累加地记录到 s 中。
判断两个字符串有无公共字符时,就可以直接让对应下标的二进制数进行与运算,为 0 则无公共字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public:
int maxProduct(vector<string>& words) {
vector<int> state;
for (auto word : words) {
int s = 0;
for (auto c : word) {
s |= 1 << (c - 'a');
}
state.push_back(s);
}

int mx = 0;
for (int i = 0; i < words.size(); i ++) {
for (int j = i + 1; j < words.size(); j ++) {
if ((state[i] & state[j]) == 0) mx = max(mx, (int) (words[i].size() * words[j].size())); // 1
}
}
return mx;
}
};
  1. 注意在 C++string.size() 返回值为 unsinged long