携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第26天,点击查看活动详情
每日刷题 2022.08.24
- leetcode原题链接:leetcode.cn/problems/as…
- 难度:中等
- 方法:位运算
题目
- 给定一个字符串数组
words,请计算当两个字符串words[i]和words[j]不包含相同字符时,它们长度的乘积的最大值。假设字符串中只包含英语的小写字母。如果没有不包含相同字符的一对字符串,返回0o。
示例
- 示例1
输入: words = ["abcw","baz","foo","bar","fxyz","abcdef"]
输出: 16
解释: 这两个单词为 "abcw", "fxyz"。它们不包含相同字符,且长度的乘积最大。
- 示例2
输入: words = ["a","ab","abc","d","cd","bcd","abcd"]
输出: 4
解释: 这两个单词为 "ab", "cd"。
- 示例3
输入: words = ["a","aa","aaa","aaaa"]
输出: 0
解释: 不存在这样的两个单词。
提示
2 <= words.length <= 10001 <= words[i].length <= 1000words[i]仅包含小写字母
解题思路
- 容易想到的做法,将所有的字符串两两进行比较(字符串中的每一个字符进行比较,可以使用indexOf()函数),如果两个字符串不存在相同的元素,那么就计算两个字符串长度的乘积,最终取乘积的最大值即可。
- 分析时间复杂度:
o(n ^ 3),因为n = 10 ^ 3,那么显然是会超时的,没有办法通过题目。
位运算
- 根据题意可知:字符串中只包含小写字母,也就是只有
26个小写字母。 - 一个整数使用二进制表示是
32位,那么通过将小写字母转换成二进制中的一位来表示,因此当两个字符串的二进制,按位与结果等于0,那么就表示这两个字符串不存在相同的字母,就可以计算两个字符串长的的乘积,最后将所有的乘积取一个最大值,返回即可。 - 时间复杂度:
o(n^2)
AC代码
var maxProduct = function(words) {
// 不存在相同的字符,每一个都需要比较的话,就会超时
// 使用位运算优化,可以提前处理位运算的值,将时间复杂度将为o(n * n + m * n)
// 如果层数过多的,可能会超时的,可以分析其是否能够将其拆分
let n = words.length, bitmask = new Array(n).fill(0).map(() => new Array(26).fill(0));
let a = 'a'.charCodeAt();
for(let i = 0; i < n; i++) {
let cur = 0;
for(let one of words[i]) {
let bit = one.charCodeAt() - a;
cur |= (1 << bit);
}
bitmask[i] = cur;
}
// console.log(bitmask)
// 26个字母中如果有1,表示当前这一位出现过
let ans = 0;
for (let i = 0; i < n; i++) {
for(let j = i + 1; j < n; j++) {
// 两两进行比较,按位与
if((bitmask[i] & bitmask[j]) === 0) {
// 不存在相同的字符
ans = Math.max(words[i].length * words[j].length, ans);
}
}
}
return ans;
};