Given a string array words
, return the maximum value of length(word[i]) * length(word[j])
where the two words do not share common letters. If no such two words exist, return 0
.
Example 1:
Input: words = ["abcw","baz","foo","bar","xtfn","abcdef"] Output: 16 Explanation: The two words can be "abcw", "xtfn".
Example 2:
Input: words = ["a","ab","abc","d","cd","bcd","abcd"] Output: 4 Explanation: The two words can be "ab", "cd".
Example 3:
Input: words = ["a","aa","aaa","aaaa"] Output: 0 Explanation: No such pair of words.
Constraints:
2 <= words.length <= 1000
1 <= words[i].length <= 1000
words[i]
consists only of lowercase English letters.Given an array of strings words
, find the maximum product of the lengths of two words that do not share any common letters. If no such pair exists, return 0.
The most efficient approach uses bit manipulation to represent each word as a bitmask. Each bit in the bitmask corresponds to a letter of the alphabet (a-z). If a word contains a letter, the corresponding bit is set to 1; otherwise, it's 0.
Two words share no common letters if and only if their bitwise AND operation results in 0. We can iterate through the words, calculating their bitmasks and checking for pairs with a bitwise AND of 0. The maximum product of lengths is then updated accordingly.
Python3
class Solution:
def maxProduct(self, words: List[str]) -> int:
masks = []
for word in words:
mask = 0
for char in word:
mask |= 1 << (ord(char) - ord('a'))
masks.append(mask)
max_product = 0
for i in range(len(words)):
for j in range(i + 1, len(words)):
if (masks[i] & masks[j]) == 0:
max_product = max(max_product, len(words[i]) * len(words[j]))
return max_product
Java
class Solution {
public int maxProduct(String[] words) {
int[] masks = new int[words.length];
for (int i = 0; i < words.length; i++) {
for (char c : words[i].toCharArray()) {
masks[i] |= 1 << (c - 'a');
}
}
int maxProduct = 0;
for (int i = 0; i < words.length; i++) {
for (int j = i + 1; j < words.length; j++) {
if ((masks[i] & masks[j]) == 0) {
maxProduct = Math.max(maxProduct, words[i].length() * words[j].length());
}
}
}
return maxProduct;
}
}
C++
class Solution {
public:
int maxProduct(vector<string>& words) {
vector<int> masks(words.size());
for (int i = 0; i < words.size(); ++i) {
for (char c : words[i]) {
masks[i] |= 1 << (c - 'a');
}
}
int max_product = 0;
for (int i = 0; i < words.size(); ++i) {
for (int j = i + 1; j < words.size(); ++j) {
if ((masks[i] & masks[j]) == 0) {
max_product = max(max_product, (int)(words[i].length() * words[j].length()));
}
}
}
return max_product;
}
};
Go
func maxProduct(words []string) int {
masks := make([]int, len(words))
for i, word := range words {
for _, char := range word {
masks[i] |= 1 << (char - 'a')
}
}
maxProduct := 0
for i := 0; i < len(words); i++ {
for j := i + 1; j < len(words); j++ {
if (masks[i] & masks[j]) == 0 {
maxProduct = max(maxProduct, len(words[i])*len(words[j]))
}
}
}
return maxProduct
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
JavaScript
/**
* @param {string[]} words
* @return {number}
*/
var maxProduct = function(words) {
const masks = words.map(word => {
let mask = 0;
for (let char of word) {
mask |= 1 << (char.charCodeAt(0) - 'a'.charCodeAt(0));
}
return mask;
});
let maxProduct = 0;
for (let i = 0; i < words.length; i++) {
for (let j = i + 1; j < words.length; j++) {
if ((masks[i] & masks[j]) === 0) {
maxProduct = Math.max(maxProduct, words[i].length * words[j].length);
}
}
}
return maxProduct;
};
These code examples all follow the same bit manipulation strategy to achieve an efficient solution to the problem. Remember to handle edge cases like empty input arrays appropriately in a production setting.