leetcode题目连接:输入一个字符串数组words,请计算不包含相同字符的两个字符串words[i]和words[j]的长度乘积的最大值。如果所有字符串都包含至少一个相同字符,那么返回0。假设字符串只包含英文小写字母。例如,输入的字符串数组words为[‘abcw‘,’foo’,’bar’,’fxyz’,’abcdef’],数组中的字符串’bar’与’foo’没有相同的字符,它们长度的乘积为9,‘abcw‘与’fxyz’也没有相同字符,长度乘积为16,这是该数组不包含相同字符的一对字符串的长度乘积的最大值。
https://leetcode.cn/problems/aseY1I/
分析:核心思想:将字母串转化为二进制位,再位与计算
假设有一个26位的二进制数,26个英文字母分别对应这26个字母,a对应最低位,b倒数第二位,依次倒推…z为最高位,如果这个字母存在,则该位置为1,若不存在则为0,这样就可以把所有的字母串表示为二进制数,再进行位与计算,若两个字母串没有相同的数字,则结果一定为0
转换的方法:假设是一个26位二进制数00…1(25个0),如果是a,则左移0位,如果是b,则左移1位…因此,转换为 1 << ('b' - 'a'),再通过位或运算合并得到字母串的“二进制数字”
b的ACSII码为98,a代表的ACSII码是97,则b-a差1
Java代码实现:class Solution {
public int maxProduct(String[] words) {
int len = words.length; //获取数组words的长度
int[] num = new int[len]; //建立一个将字母串表示为二进制数的数组
for(int i = 0; i < len; i++){ //遍历words数组中的每个元素
for(int j = 0; j < words[i].length(); j++){ //遍历words[i]中某个元素中的所有元素
num[i] |= (1 << (words[i].charAt(j) - 'a')); //位或运算,合并遍历的每个字母的“二进制”得到字母串的“二进制”
}
}
int result = 0; //设定一个result
for(int i = 0; i < len-1; i++){ //第一个字母串
for(int j =0; j < len; j++){ //第二个字母串
if((num[i]&num[j]) == 0 ){ //位与计算为0情况:无重复字母
result = Math.max(result,words[i].length()*words[j].length());
}
}
}
return result;
}
}
注意:
1、关于length与length()的区别,length是用来获取数组的长度,length()是用来获取字符串的长度
2、Math称之为数学函数:Math.max/Math.min 获取最大值和最小值
复杂度分析:
时间复杂度:O(n^2+L),其中n是数组words的长度,计算单词长度的最大乘积时需要O(n^2)的时间遍历每一对单词;L是数组中所有单词的长度之和,将所有的单词转化为二进制需要O(L)的时间遍历所有单词。
空间复杂度:O(n),n是数组words的长度,需要创建长度为n的数组存储每个单词的二进制表示
代码执行结果:以上为个人做题笔记,很多是自己的理解,若有错误还请各位大佬指出~



