Algorithm 计数在整数范围内设置每个位的次数
给定从M到N的整数范围,其中 M和N可能不是2的幂。有没有 一种有效的方法来计算每次的次数 位设置好了吗 例如,范围为0到10Algorithm 计数在整数范围内设置每个位的次数,algorithm,bit-manipulation,Algorithm,Bit Manipulation,给定从M到N的整数范围,其中 M和N可能不是2的幂。有没有 一种有效的方法来计算每次的次数 位设置好了吗 例如,范围为0到10 0 0000 1 0001 2 0010 3 0011 4 0100 5 0101 6 0110 7 0111 8 1000 9 1001 10 1010 我希望在每列中设置每个位的时间计数,在这种情况下为3,4,5,5。每个位级别都有一个模式,由2^power0s和2^power1s组成 因此有三种情况: 当M和N是M=0模
0 0000
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001
10 1010
我希望在每列中设置每个位的时间计数,在这种情况下为3,4,5,5。每个位级别都有一个模式,由
2^power
0s和2^power
1s组成
因此有三种情况:
M
和N
是M=0模2^(幂+1)
和N=2^(幂+1)-1模2^(幂+1)
时。在这种情况下,答案只是(N-M+1)/2
M
和N
为整数除以2^(幂+1)
时,M和N=相同的数字。在这种情况下,有几个子类别:
M
和N
都是这样的:当整数除以2^(幂)
时,M
和N
=相同的数字。在这种情况下,如果N<2^(power)mod 2^(power+1)
,则答案为0
,否则答案为N-M+1
N-(N/2^(power+1))*2^(power+1)+2**(power)
(整数除法),如果N>2^(power)mod 2^(power+1)
,否则答案是(M/2^(power+1))*2^(power+1)-1-M
2^(幂+1)
时,M和N=不同的数字。在这种情况下,您可以将1和2的技术结合起来。查找M
和(M/(2^(幂+1))+1)*(2^(幂+1))-1之间的数字数。然后在(M/(2^(power+1))+1)*(2^(power+1))
和(N/(2^(power+1)))*2^(power+1)-1之间。最后在(N/(2^(power+1))*2^(power+1)
和N
之间
def case1(M, N):
return (N - M + 1) // 2
def case2(M, N, power):
if (M > N):
return 0
if (M // 2**(power) == N // 2**(power)):
if (N % 2**(power+1) < 2**(power)):
return 0
else:
return N - M + 1
else:
if (N % 2**(power+1) >= 2**(power)):
return N - (getNextLower(N,power+1) + 2**(power)) + 1
else:
return getNextHigher(M, power+1) - M
def case3(M, N, power):
return case2(M, getNextHigher(M, power+1) - 1, power) + case1(getNextHigher(M, power+1), getNextLower(N, power+1)-1) + case2(getNextLower(N, power+1), N, power)
def getNextLower(M, power):
return (M // 2**(power))*2**(power)
def getNextHigher(M, power):
return (M // 2**(power) + 1)*2**(power)
def numSetBits(M, N, power):
if (M % 2**(power+1) == 0 and N % 2**(power+1) == 2**(power+1)-1):
return case1(M,N)
if (M // 2**(power+1) == N // 2**(power+1)):
return case2(M,N,power)
else:
return case3(M,N,power)
if (__name__ == "__main__"):
print numSetBits(0,10,0)
print numSetBits(0,10,1)
print numSetBits(0,10,2)
print numSetBits(0,10,3)
print numSetBits(0,10,4)
print numSetBits(5,18,0)
print numSetBits(5,18,1)
print numSetBits(5,18,2)
print numSetBits(5,18,3)
print numSetBits(5,18,4)
def案例1(M,N):
返回(N-M+1)//2
def箱2(M、N、电源):
如果(M>N):
返回0
如果(M//2**(功率)==N//2**(功率)):
如果(N%2**(功率+1)<2**(功率)):
返回0
其他:
返回N-M+1
其他:
如果(N%2**(功率+1)>=2**(功率)):
返回N-(getNextLower(N,power+1)+2**(power))+1
其他:
返回getNextHigher(M,power+1)-M
def壳体3(M、N、电源):
返回case2(M,getNextHigher(M,power+1)-1,power)+case1(getNextHigher(M,power+1),getNextLower(N,power+1)-1)+case2(getNextLower(N,power+1),N,power)
def getNextLower(M,功率):
返回(M//2**(功率))*2**(功率)
def getNextHigher(M,电源):
返回(M//2**(功率)+1)*2**(功率)
def数值(M、N、功率):
如果(M%2**(功率+1)==0和N%2**(功率+1)==2**(功率+1)-1):
返回案例1(M,N)
如果(M//2**(幂+1)=N//2**(幂+1)):
返回壳体2(M、N、电源)
其他:
返回壳体3(M、N、电源)
如果(\uuuuu name\uuuuuu==“\uuuuuu main\uuuuuu”):
打印数字位(0,10,0)
打印数字位(0,10,1)
打印数字位(0,10,2)
打印数字位(0,10,3)
打印数字位(0,10,4)
打印数字位(5,18,0)
打印数字位(5,18,1)
打印数字位(5,18,2)
打印数字位(5,18,3)
打印数字位(5,18,4)
它可以像-
取x1=0001(用于在最右边的列中查找1),x2=0010,x3=0100,依此类推
现在,在一个循环中-
n1 = n2 = n3 = 0
for i=m to n:
n1 = n1 + (i & x1)
n2 = n2 + (i & x2)
n3 = n3 + (i & x3)
在哪里-
ni=第i列中的1个数(从右起)这可能是最慢的方式,仍然有意义。这就是为什么我说它是最简单的,而不是最好的:)可能可以做一些简化,但我将把它作为练习留给读者。