Description:
Given a string array words
, find the maximum value of length(word[i]) * length(word[j])
where the two words do not share common letters. You may assume that each word will contain only lower case letters. If no such two words exist, return 0.
Example 1:
Given ["abcw", "baz", "foo", "bar", "xtfn", "abcdef"]
Return 16
The two words can be "abcw", "xtfn"
.
Example 2:
Given ["a", "ab", "abc", "d", "cd", "bcd", "abcd"]
Return 4
The two words can be "ab", "cd"
.
Example 3:
Given ["a", "aa", "aaa", "aaaa"]
Return 0
No such pair of words.
Solution 1:WA
一开始的方法想错了,以为可以用并查集做,把凡是有相同char的word放到同一组中,然后在不同的组之间做乘法。
但是后来发现这个想法有bug,比如ab,bc,cd是同一组,但是ab和cd也可以做乘法。
因为并查集好久没写了,所以还是贴上来回忆一下。
<span style="font-size:18px;">import java.util.Arrays;
public class Solution {
public int maxProduct(String[] words) {
int n = words.length;
DisjointSet ds = new DisjointSet(n + 26);
for (int i = 0; i < n; i++) {
String str = words[i];
for (int j = 0; j < str.length(); j++) {
int ch = str.charAt(j) - 'a' + n;
ds.union(ch, i);
}
}
int arr[] = new int[26];
for (int i = 0; i < n; i++) {
int ch = ds.find(i) - n;
System.out.printf("word %d belongs to %d \n", i, ch);
arr[ch] = Math.max(arr[ch], words[i].length());
}
int max = 1;
for (int i = 0; i < 26; i++)
for (int j = i + 1; j < 26; j++)
max = Math.max(max, arr[i] * arr[j]);
for (int i = 0; i < 26; i++) {
System.out.println((char) (i + 'a') + " " + arr[i]);
}
return max;
}
class DisjointSet {
int n;
int father[];
DisjointSet(int n) {
this.n = n;
father = new int[n];
for (int i = 0; i < n; i++)
father[i] = i;
}
public int find(int x) {
if (x == father[x])
return x;
father[x] = find(father[x]);
return father[x];
}
public void union(int a, int b) {
int ra = find(a);
int rb = find(b);
if (ra == rb)
return;
father[rb] = ra;
}
}
}</span>
Solution 2:
突然发现既然所有的char都是在'a'-'z'之间,那么如果我将每个word转成26位的long,再做乘法运算就可以。
import java.util.Arrays;
public class Solution {
public int maxProduct(String[] words) {
int n = words.length;
long[] words_binary = new long[n];
for (int i = 0; i < n; i++) {
String str = words[i];
for (int j = 0; j < str.length(); j++)
words_binary[i] |= (1l << (str.charAt(j) - 'a'));
}
int max = 0;
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
if ((words_binary[i] & words_binary[j]) == 0)
max = Math.max(max, words[i].length() * words[j].length());
return max;
}
public static void main(String[] args) {
Solution s = new Solution();
String[] arr = { "abcw", "baz", "foo", "bar", "xtfn", "abcdef" };
// System.out.println(Long.toBinaryString(1l << 25));
System.out.println(s.maxProduct(arr));
}
}