题目描述
给定一个字符串数组 words,找到 length(word[i]) * length(word[j]) 的最大值,并且这两个单词不含有公共字母。你可以认为每个单词只包含小写字母。如果不存在这样的两个单词,返回 0。
输入: [“abcw”,“baz”,“foo”,“bar”,“xtfn”,“abcdef”]
输出: 16
解释: 这两个单词为 “abcw”, “xtfn”。
思路
可以看到数据返回 n 在 1000 以内。
由此可知 n^2 以内的算法都是可以接受的。
那么我就是用了 两层 for 循环。
class Solution {
public static Set<Character> wset = new HashSet();
public int maxProduct(String[] words) {
int ret = 0;
for (int i = 0; i < words.length - 1; i++) {
for (int j = i + 1; j < words.length; j++) {
if (!isRepeate(words[i], words[j])) {
ret = Math.max(ret, words[i].length() * words[j].length());
}
}
}
return ret;
}
public boolean isRepeate(String a, String b) {
char[] achs = a.toCharArray();
char[] bchs = b.toCharArray();
for (char c: achs) {
wset.add(c);
}
for (char c: bchs) {
if (wset.contains(c)) {
wset.clear();
return true;
}
}
wset.clear();
return false;
}
}
成功 ac ,只是用时和内存表现都不好。
题解
解法一
class Solution {
public int maxProduct(String[] words) {
int length = words.length;
int[] masks = new int[length];
for (int i = 0; i < length; i++) {
String word = words[i];
int wordLength = word.length();
for (int j = 0; j < wordLength; j++) {
masks[i] |= 1 << (word.charAt(j) - 'a');
}
}
int maxProd = 0;
for (int i = 0; i < length; i++) {
for (int j = i + 1; j < length; j++) {
if ((masks[i] & masks[j]) == 0) {
maxProd = Math.max(maxProd, words[i].length() * words[j].length());
}
}
}
return maxProd;
}
}
与我判断两个字符串是否有相同 字符 的方法不一样。这里使用将 26 个字母用位表示,两个字符串的位表示 & 之后 = 0 则表示没有重复。
解法二
class Solution {
public int maxProduct(String[] words) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
int length = words.length;
for (int i = 0; i < length; i++) {
int mask = 0;
String word = words[i];
int wordLength = word.length();
for (int j = 0; j < wordLength; j++) {
mask |= 1 << (word.charAt(j) - 'a');
}
if (wordLength > map.getOrDefault(mask, 0)) {
map.put(mask, wordLength);
}
}
int maxProd = 0;
Set<Integer> maskSet = map.keySet();
for (int mask1 : maskSet) {
int wordLength1 = map.get(mask1);
for (int mask2 : maskSet) {
if ((mask1 & mask2) == 0) {
int wordLength2 = map.get(mask2);
maxProd = Math.max(maxProd, wordLength1 * wordLength2);
}
}
}
return maxProd;
}
}
比解法一稍微优化了一些,用 map 存储代替数组,只存储相同字母表示的单词中最长的那个。
但是实际测下来还不如解法一。
参考资料
https://blog.csdn.net/qq_43406895/article/details/121373928
https://leetcode-cn.com/problems/maximum-product-of-word-lengths/