返回
318. 最大单词长度乘积: 经典「状态压缩 + 位运算」入门题
后端
2023-10-07 03:35:29
1. 题意理解
给出由小写字母组成的数组 words
,需要你返回所有 words
中两个不相交的子数组的最大单词长度乘积。如果数组长度为 n
,那么子数组的最大长度就是 n-1
。
2. 解题思路
这道题的关键在于对问题进行「状态压缩」,将数组 words
中的每个单词转化为一个二进制位,然后使用「位运算」来找出所有不相交子数组的单词长度乘积。
3. 详细解法
为了进行「状态压缩」,首先需要定义一个二进制位来表示每个单词。对于数组 words
中的第 i
个单词,我们将其表示为二进制位 mask[i]
。
-
将每个单词转换为二进制位:
- 将每个单词中的每个小写字母映射为一个二进制位,例如,
a
映射为00000001
,b
映射为00000010
,以此类推。 - 将每个单词中的所有二进制位合并为一个二进制位
mask[i]
。例如,单词"abc"
的二进制位是00000111
。
- 将每个单词中的每个小写字母映射为一个二进制位,例如,
-
使用「位运算」找出所有不相交子数组:
- 定义一个变量
dp[i]
来存储以数组words
中第i
个单词结尾的所有不相交子数组的最大单词长度乘积。 - 初始化
dp[0] = 0
。 - 从
i = 1
开始循环到n
:- 对于数组
words
中的第j
个单词,如果mask[i]
和mask[j]
没有相同的二进制位,则说明子数组words[i]
和words[j]
是不相交的。 - 更新
dp[i]
为max(dp[i], dp[j] + length(words[i]) * length(words[j]))
,其中length(word)
表示单词word
的长度。
- 对于数组
- 定义一个变量
-
返回
max(dp[1], dp[2], ..., dp[n])
即可得到最终结果。
4. 代码示例
def maxProduct(words):
n = len(words)
mask = [0] * n
dp = [0] * n
for i in range(n):
for c in words[i]:
mask[i] |= 1 << (ord(c) - ord('a'))
for i in range(1, n):
for j in range(i):
if mask[i] & mask[j] == 0:
dp[i] = max(dp[i], dp[j] + len(words[i]) * len(words[j]))
return max(dp)
5. 结语
这道题通过「状态压缩」和「位运算」两个技巧巧妙地解决了问题,展现了算法在解决实际问题中的强大威力。希望你能通过这道题学到新的算法技巧,并将其运用到其他的算法问题中去。