📅  最后修改于: 2023-12-03 15:27:34.666000             🧑  作者: Mango
给定一个长度为 $n$ 的二进制字符串 $s$,以及一个整数 $k$,求 $s$ 的所有长度为 $k$ 的子字符串的按位或的结果中 1 的个数。
最简单的方法是暴力枚举所有长度为 $k$ 的子字符串并计算按位或的结果中 1 的个数。时间复杂度为 $\mathcal{O}(n k)$。
def brute_force(s: str, k: int) -> int:
count = 0
for i in range(n - k + 1):
or_result = int(s[i], 2)
for j in range(i + 1, i + k):
or_result |= int(s[j], 2)
count += bin(or_result).count('1')
return count
在 Brute Force 的基础上,我们可以使用一些位运算技巧来优化时间复杂度。
假设 $s$ 中第 $i$ 位上为 1,则该位对应的二进制数为 $2^i$,因此所有子字符串的按位或的结果可以表示为这些二进制数的按位或和。
对于长度为 $k$ 的子字符串,我们可以先计算其中前 $k-1$ 位对应的二进制数的按位或和,然后再加上第 $k$ 个位置上的二进制数。
例如,对于长度为 3 的子字符串 "110",其按位或的结果为 $2^1 + 2^2 = 6$。
由于 $2^i$ 在二进制下只有一位为 1,因此我们可以使用 XOR 操作来消去已经遍历过的二进制数,这样可以避免重复计算。
时间复杂度为 $\mathcal{O}(n)$。
def bitwise_trick(s: str, k: int) -> int:
count = 0
n = len(s)
or_result = 0
for i in range(k - 1):
or_result |= int(s[i], 2)
for i in range(k - 1, n):
or_result |= int(s[i], 2)
count += bin(or_result).count('1')
or_result ^= int(s[i - k + 1], 2)
return count
本文介绍了两种解决给定二进制字符串的所有 K 长度子字符串的按位或中的 setbit 计数的方法:暴力枚举和位运算技巧。位运算技巧可以将时间复杂度降低到 $\mathcal{O}(n)$,因此更为高效。