题目
给定一个字符串数组 words,请计算当两个字符串 words[i] 和 words[j] 不包含相同字符时,它们长度的乘积的最大值。假设字符串中只包含英语的小写字母。如果没有不包含相同字符的一对字符串,返回 0。
- 输入与输出
输入: words = [“abcw”,“baz”,“foo”,“bar”,“fxyz”,“abcdef”]
输出: 16
解释: 这两个单词为 “abcw”, “fxyz”。它们不包含相同字符,且长度的乘积最大。
思路
-
暴力枚举
最开始想到的就是暴力枚举,逐一对比。但是效率太低了。时间复杂度 O(n^4),确实挺大。 -
位运算 + 比特位作为哈希set
后来在题解中看到了大佬的解法,效率确实高。
具体思路看代码。
代码
- 暴力枚举
class Solution {
public int maxProduct(String[] words) {
// 定义相同的单词标记
boolean[][] isSame = new boolean[words.length][words.length];
int res = 0;
for(int i = 0; i < words.length-1; i++) {
for (int j = i+1; j < words.length; j++) {
if (i == j) continue;
if (isSame[i][j]) continue;
if (isDifferent(words[i],words[j])) {
int tmp = words[i].length() * words[j].length();
if (tmp > res) {
res = tmp;
}
}else {
isSame[i][j] = true;
}
}
}
return res;
}
public boolean isDifferent(String s1, String s2) {
char[] charS1 = s1.toCharArray();
char[] charS2 = s2.toCharArray();
for (int i = 0; i < charS1.length; i++) {
for (int j = 0; j < charS2.length; j++) {
if (charS1[i] == charS2[j]) {
return false;
}
}
}
return true;
}
}
- 位运算
class Solution {
public int maxProduct(String[] words) {
int length = words.length;
int[] word = new int[length];
for (int i = 0; i < words.length; i++) {
for (int j = 0; j < words[i].length(); j++) {
// 用 比特位 来存储当前有哪些字母
// abc ==> 111
// acf ==> 100101
word[i] |= (1 << (words[i].charAt(j) - 'a'));
// 位运算
// abc
// word[0] = 0 | (1 << 0) ==> word[0] = 1 001
// word[0] = 1 | (1 << 1) ==> word[0] = 3 011
// word[0] = 2 | (1 << 2) ==> word[0] = 7 111
}
}
int res = 0;
for (int i = 0; i < length; i++) {
for (int j = i+1; j < length; j++) {
// 如果 当前单词 & 比较单词 == 0 说明是不相同的
// abc ==> 000111
// def ==> 111000
// abc & def = 0
if ((word[i] & word[j]) == 0) {
res = Math.max(res,words[i].length() * words[j].length());
}
}
}
return res;
}
}