318 Maximum Product of Word Lengths
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:
Solution:
Solution1:
class Solution {
public int maxProduct(String[] words) {
List<Set<Character>> list = new ArrayList<Set<Character>>();
for (String word : words){ // O(n)
Set<Character> set = new HashSet<Character>();
for (int i = 0; i < word.length(); i++){ // O(L)
set.add(word.charAt(i));
}
list.add(set);
}
/*
{<a,b,c,w>, <b, a, z>, <f,o>, <b,a,r>, <x, t, f, n> <a, b, c, d, e, f>}
*/
int largest = 0;
for (int i = 0; i < words.length; i++){ // O(N)
for (int j = i + 1; j < words.length; j++){ // O(N)
if (isValid(list.get(i), words[j])){ // O(L)
// <a,b,c,w> , xtfn
int cur = words[i].length() * words[j].length();
// 4 * 4
largest = Math.max(cur, largest);
}
}
}
return largest;
}
private static boolean isValid(Set<Character> set, String word){
// <a,b,c,w>, xtfn
for (int i = 0; i < word.length(); i++){
if (set.contains(word.charAt(i))){
return false;
}
}
return true;
}
}
// TC: O(N^2 * L)
// SC: O(N*L)
Solution2:
class Solution {
public int maxProduct(String[] words) {
// Assumptions: words is not null and has length >= 2;
// there is no null String in the dict.
// The words in the dict only use characters 'a' - 'z'.
// Get the bit mask for each of the word in the dict,
// the bit mask is represented by the lower 26 bits of an integer.
// each of the bit represents one of the characters in 'a' - 'z'.
Map<String, Integer> bitMasks = getBitMasks(words);
// sort the dict by length of the words in descending order.
Arrays.sort(words, new Comparator<String>(){
@Override
public int compare(String s0, String s1){
if (s0.length() == s1.length()){
return 0;
}else if (s0.length() < s1.length()){
return 1;
}else{
return -1;
}
}
});
int largest = 0;
// note the order of constructing all the pairs,
// we make our best to try largest product.
for (int i = 1; i < words.length; i++){
for (int j = 0; j < i; j++){
// early break if the product is already smaller than
// the current largest one.
int prod = words[i].length() * words[j].length();
if (prod <= largest){
break;
}
int iMask = bitMasks.get(words[i]);
int jMask = bitMasks.get(words[j]);
if ((iMask & jMask) == 0){
largest = prod;
}
}
}
return largest;
}
// Get the bit mask for each of the words.
private Map<String, Integer> getBitMasks(String[] words){
Map<String, Integer> map = new HashMap<String, Integer>();
for (String word : words){
int bitMask = 0;
for (int i = 0; i < word.length(); i++){
// the 26 characters 'a' - 'z' are mapped to 0-25th bit.
// to determine which bit it is for a character x,
// use (x - 'a') since their values are in a consecutive range.
// if character x existes in the word, we set the bit at
// corresponding index to 1.
bitMask |= 1 << (word.charAt(i) - 'a');
}
map.put(word, bitMask);
}
return map;
}
}
// TC: O(n^2 + |sum of all words' length|))
// SC: O(n)