1. 获得2的k次幂
若数字n为2的k次幂,即存在n=2kn = 2^kn=2k成立。我们可以通过对1进行左移k位的操作来得到n=2kn = 2^kn=2k。
k = 10
n = 1 << k
print(f"n = {n}, n是2的{k}次幂")
print(f"n的二进制表示是{bin(n)}")
2. 获得二进制数字只包含k个1的数字
若想得到一个二进制数字只包含k个1的数字,我们可以通过对1进行左移k位再减1的操作来得到n=2k−1n = 2^k-1n=2k−1。
k = 10
n = (1 << k) - 1
print(f"n = {n}, n是2的{k}次幂-1")
print(f"n的二进制表示是{bin(n)},其中包含{k}个1")
3. 判断n是否为2的幂
若数字n为2的k次幂,即存在n=2kn = 2^kn=2k成立,那么其二进制的首位一定是1,后面包含了k个0。
如16 = 0b10000,其二进制的首位为1,后面包含了4个0。
如果考虑n-1的二进制,容易发现其位数应该比n少1,同时均为1构成。
如15 = 0b1111,其二进制为4个1
由于只有当n是2的幂,才会具备上述性质,我们可以使用与运算来判断n是否为2的幂。
当且仅当 n & (n-1) == 0 成立时,n为2的幂。题目 LeetCode231. 2 的幂 使用到该技巧。
同理,如果要判断n的二进制是否均由1构成,也可以用类似的方法判断。
当且仅当n & (n+1) == 0 成立时,n的二进制均由1构成。
n = 16
if n & (n-1) == 0:
print("n是2的幂")
n = 15
if n & (n+1) == 0:
print("n的二进制数均由1构成")
4. 把n的二进制最低连续k位均改为0
有时候我们需要进行如下操作,把数字n的二进制最低连续k位(从低位数起,从1数起)均改为0。
譬如,我们存在n = 0b101001,想将其中的最低连续4位均改为0,令n变为n = 0b100000。
根据左移和右移操作的知识,我们知道
- 右移移动k位,可以删除最低k位
- 左移移动k位,可以在填充k个0在最低位。
故我们可以结合上述操作,先右移k位,再左移k位,将n的二进制最低连续k位均改为0。
n = 0b101001
k = 4
# 先右移k位,再左移k位,得到n = 0b100000
n >>= k
n <<= k
5. 把n中二进制第k位从0改为1
有时候我们需要进行如下操作,把数字n的二进制的第k位(从低位数起,从0数起)从0改为1。
譬如,我们存在n = 0b101001,想将其中的第4位从0修改为1,令n变为n = 0b010000。
我们可以令n和m = 0b010000(除了第k位为1,其他位均为0的一个二进制数)进行或运算。
n = 0b101001
m = 0b010000
# 或运算得到 0b111001
ans = bin(n | m)
因此问题转变为,我们如何找到这个m。
这个m其实就是2的k次幂,根据前面的知识,我们可以通过如下的方式可以找到m。
n = 0b101001
# 使用左移运算得到 m = 0b010000,末尾包含 k 个 0
k = 4
m = 1 << k
# 或运算得到 0b111001
ans = bin(n | m)
6. 把n的二进制第k位从1改为0
有时候我们需要进行如下操作,把数字n的二进制的第k位(从低位数起,从0数起)从1改为0。
譬如,我们存在n = 0b101001,想将其中的第3位从1修改为0,令n变为n = 0b100001。
我们可以令n和m = 0b110111(除了第k位为0,其他位均为1的一个二进制数)进行与运算。
n = 0b101001
m = 0b110111
# 与运算得到 0b100001
ans = bin(n & m)
因此问题转变为,我们如何找到这个m。
如果我们能够找到二进制数0b001000,再令其中的每一位都取反,即可得到m = 0b110111。
二进制数0b001000是2的k次幂,根据前面的知识,我们可以通过如下的方式可以找到m。
n = 0b101001
# 使用左移运算和取反运算得到 m = 0b110111,末尾包含 k 个 1
k = 3
m = ~(1 << k)
# 与运算得到 0b100001
ans = bin(n & m)
727



被折叠的 条评论
为什么被折叠?



