📅  最后修改于: 2023-12-03 15:25:22.877000             🧑  作者: Mango
在编程中,经常需要找到小于或等于给定数的2的最高幂。这个问题可以使用位运算来解决。
我们可以将给定数左移一位(即乘以2),并将其与1进行与运算,以此来判断上一个数(即除以2后的数)是否为奇数。如果是奇数,则保留当前的移位值(即乘以2之后的值),否则将移位值减半(即除以2)。
def get_pow_two(n):
if n <=0:
return -1
pow_two = 1
while pow_two * 2 <= n:
pow_two <<= 1 # 左移一位,即乘以2
if (n >> 1) & 1: # 如果上一个数是奇数
pow_two += 1 # 保留当前移位值
return pow_two
以上代码的时间复杂度为 $O(log_{2} n)$
我们可以将给定数的最高位(即左边第一个不为0的位)之后的所有位设为1,然后将其反转,即可得到小于或等于给定数的2的最高幂。
def reverse_bits(n):
# 将二进制数反转
result = 0
for i in range(32):
result <<= 1
result |= n & 1
n >>= 1
return result
def get_pow_two(n):
if n <= 0:
return -1
n |= (n >> 1)
n |= (n >> 2)
n |= (n >> 4)
n |= (n >> 8)
n |= (n >> 16)
return reverse_bits(n) >> 1
以上代码的时间复杂度为 $O(1)$,但它并不是万无一失的。如果给定的数是负数,则它的二进制表示的最高位为1,上述算法会将其全部置为1,从而得到错误的结果。为了避免出现这种情况,可以在函数中进行额外的判断。
def get_pow_two(n):
if n <= 0:
return -1
# 如果是负数,则返回0
if n < 0:
return 0
n |= (n >> 1)
n |= (n >> 2)
n |= (n >> 4)
n |= (n >> 8)
n |= (n >> 16)
return reverse_bits(n) >> 1
这两种方法各有优缺点。方法一虽然时间复杂度为 $O(log_{2} n)$,但是对于任何正整数都是正确的。方法二虽然时间复杂度为 $O(1)$,但是对于负数的处理可能会出现问题。在实际应用中,需要根据具体情况来选择使用哪种方法。