题目
链接:https://leetcode.cn/problems/aseY1I/
给定一个字符串数组 words,请计算当两个字符串 words[i] 和 words[j] 不包含相同字符时,它们长度的乘积的最大值。假设字符串中只包含英语的小写字母。如果没有不包含相同字符的一对字符串,返回 0。
思路
首先我们肯定是要遍历这个数组里的每个word了,双重遍历数组,保证每两个元素都能对比上。
重点的问题是:
- 如何判断两个字符串中有相同的字符。想要高效的处理,还是得用位运算。
- 找到最大值。
解法:位运算
逻辑
我们用位运算来解决判断两个字符串中是否有相同字符的问题。
将abcde……对应成数字01234。用一个26位长的二进制数字,来记录哪个字符出现过。
比如字符串abea和efgg对应的二进制值,以及二者做&运算后的值,如图所示:
因为有相同的字符,因此结果是大于0的。
所以我们的主要逻辑是:
- 遍历字符串数组,将每个字符串中字符出现的情况保存为二进制对应的数字,保存到一个整型数组中
- 使用一个变量缓存最大积。
- 再次遍历这个整形数组,通过&运算来判断是否存在相同数字。如果不存咋,则计算二者长度的积,和缓存的最大积比较,当前结果大则替换
代码
public int maxProduct(String[] words) {
// 将每个字符串中字符出现的结果,保存到整型数组里
int[] temp = new int[words.length];
for (int i = 0; i < words.length; i++) {
for (int j = 0; j < words[i].length(); j++) {
// 使用|运算符将字符words[i].charAt(j)在二进制temp[i]的对应位置置为1
temp[i] |= 1 << (words[i].charAt(j) - 'a');
}
}
// 保存最大值
int max = 0;
for (int i = 0; i < temp.length; i++) {
for (int j = i + 1; j < temp.length; j++) {
// 使用&运算符对比第i个单词和第j个单词中是否有相同数字
if ((temp[i] & temp[j]) == 0) {
int multiplyResult = words[i].length() * words[j].length();
max = Math.max(max, multiplyResult);
}
}
}
return max;
}
一些思考
算法题中,bitmap和位运算实在是太常用了。