题目:LCR 005
解法一:二进制转换 + 位运算
-
双循环遍历所有字符串组合
-
判断二者是否有相同字母
- 26位的二进制数字,每位为1代表字符串中有该字母,为0则没有。如:"10000 10000 10000 10000 10000 1"代表字符串中包含了a、f、k、p、u、z,但出现次数无法确认(至少出现了1次)
- 将两个字符串代表的二进制数字进行按位与运算,若结果为0,则代表二者没有重复字符
-
没有相同字母时,更新最大乘积
class Solution {
public int maxProduct(String[] words) {
int res = 0;
for (int i = 0; i < words.length; i++) {
for (int j = i + 1; j < words.length; j++) {
int x = 0, y = 0;
for (int m = 0; m < words[i].length(); m++) {
x |= 1 << ('z' - words[i].charAt(m));
}
for (int n = 0; n < words[j].length(); n++) {
y |= 1 << ('z' - words[j].charAt(n));
}
if ((x & y) == 0) res = Math.max(res, words[i].length() * words[j].length());
}
}
return res;
}
}
解法二:解法一优化
由于最后是通过字符串代表的二进制进行判断,那么我们可以直接将所有字符串代表的二进制数字存储,并存储其最大长度(如:"ab"和"aaaabbbbb"代表的二进制数字相同,"11000 00000 00000 00000 0"表示的字符串最大长度为9),遍历时直接遍历我们存储的二进制Map即可
class Solution {
public int maxProduct(String[] words) {
int res = 0;
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < words.length; i++) {
int x = 0;
for (int y = 0; y < words[i].length(); y++) {
x |= 1 << ('z' - words[i].charAt(y));
}
map.put(x, Math.max(map.getOrDefault(x, 0), words[i].length()));
}
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
for (Map.Entry<Integer, Integer> entry1 : map.entrySet()) {
if ((entry.getKey() & entry1.getKey()) == 0)
res = Math.max(res, entry.getValue() * entry1.getValue());
}
}
return res;
}
}
注意:Map无序,双循环遍历时会遇到与自身进行与运算的情况,但不会为0,所以对计算结果无影响