318. 最大单词长度乘积

191 阅读2分钟

「这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战」。

题目

给定一个字符串数组 words,找到 length(word[i]) * length(word[j]) 的最大值,并且这两个单词不含有公共字母。你可以认为每个单词只包含小写字母。如果不存在这样的两个单词,返回 0。

截屏2021-11-17 下午11.56.24.png

思路分析

先尝试一个最笨的思路,两层for循环遍历i,j,比较word[i],words[j]看看是否有公共字母,如果没有公共字母,则两者长度相乘,并更新最大单词长度乘积。

而比较words[i],words[j]的时间复杂度本身为n**2,因此会造成总复杂度过大。

所以应该想办法使words[i],words[j]比较公共字母这步时间复杂度变小,我们能否通过子问题的方式解决这个时间复杂度呢?不能,因此选择位运算。

位运算用来比较两个字符串是否有相同字符,位运算总共有且,或,异或三种常见写法,这里很明显使用且更合适些。

//将单词按照26字母分为26位
//使用如下方法可以不在意字母的顺序(不用从是否有a,是否有b的顺序判断)
int wordLength = word.size();
for (int j = 0; j < wordLength; j++) {
    masks[i] |= 1 << (word[j] - 'a');
}

简单说说

这篇文章拖了好久,一个是看了五分钟真不会(因为往动态规划想了好久),一个是断了签积极性确实也没有了。不过事后看题解·发现这题确实也不难,先穷举再剪枝的思路还是没有变,只是剪枝逻辑变成了位运算。

说到位运算可能有些人不熟悉,其实也就是个吃过见过的事

可以看看我之前写的这篇文章:没时间看CSAPP?那总要看看实验吧——DATALAB