携手创作,共同成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第22天,点击查看活动详情
最大单词长度乘积
给你一个字符串数组
words
,找出并返回length(words[i]) * length(words[j])
的最大值,并且这两个单词不含有公共字母。如果不存在这样的两个单词,返回0
。
分析
- 给到一个字符串数组,要找到没有公共字母的两个最长单词长度的乘积,可以直接暴力解决
暴力
- 双重遍历这个数组,使用一个变量来维护长度的乘积的最大值,查看当前第i个和第j个有没有公共字母,如果没有公共字母就更新乘积
- 描述起来比较简单,因此代码也不是很复杂
代码
const compare = (a, b) => {
for (let i = 0; i < a.length; i++){
if ( b.includes(a[i]) ){
return false;
}
}
return true;
};
const maxProduct = function(words) {
let max = 0;
for (let i = 0; i < words.length - 1; i++) {
for (let j = i + 1; j < words.length; j++) {
const a = words[i];
const b = words[j];
let unique = true;
if ( compare(words[i], words[j]) ) {
max = Math.max( max, (words[i].length * words[j].length) )
}
}
}
return max;
};
- 但是暴力解决看上去过于暴力了,这道题怎么着也是中等难度,尊重一下这道题的难度,进行一下优化,要判断是否有相同的字母,对于判断某个位置是否相同,好像可以使用位运算
位运算
- 每个字母都有其ASCII码,所以把每个位置上的字母转换成位掩码,通过按位与,只要有一个为0,就是0,如果相同就是1
- 生成位掩码:定义每个字符对应的数字,a-z分别为0-25,单词的每个字符对应的数字c就是生成二进制码的位数,每个字符生成的二进制通过或运算得到一个单词对应的位掩码
- 所以就可以把字符串的比较转为位掩码的按位与运算,可以在拿到数组的时候全部转为位掩码后计算长度的最大乘积
代码
const convertToInt = str => {
let int = 0
const baseCharCode = ('a').charCodeAt(0)
for (let i = 0; i < str.length; i++) {
int |= 1 << (str.charCodeAt(i) - baseCharCode)
}
return int
}
const compare = (a, b) => {
if ((a & b) === 0) return true
else return false
}
const maxProduct = function(words) {
const ints = words.map(word => convertToInt(word))
let max = 0
for (let i = 0; i < ints.length - 1; i++) {
for (let j = i + 1; j < ints.length; j++) {
if ( compare(ints[i], ints[j]) ) {
max = Math.max( max, (words[i].length * words[j].length) )
}
}
}
return max
};
总结
- 位运算总是用在不经意间,出现在前端的概率较低,但是对于按位比较异同的敏感度还是要有的,毕竟JavaScript支持位运算
- 今天也是有收获的一天