题目:
Given two integers
L
andR
, find the count of numbers in the range[L,R]
(inclusive) having a prime number of set bits in their binary representation. (Recall that the number of set bits an integer has is the number of 1s present when written in binary. For example,21
written in binary is10101
which has 3 set bits. Also, 1 is not a prime.)
Example 1:Input: L = 6, R = 10 Output: 4 Explanation: 6 -> 110 (2 set bits, 2 isprime) 7 -> 111 (3 set bits, 3 is prime) 9 -> 1001 (2 set bits , 2 is prime) 10->1010 (2 set bits , 2 is prime)
Example 2:
Input: L = 10, R = 15 Output: 5 Explanation: 10 -> 1010 (2 set bits, 2 is prime) 11 -> 1011 (3 set bits, 3 is prime) 12 -> 1100 (2 set bits,2 is prime) 13 -> 1101 (3 set bits, 3 is prime) 14 -> 1110 (3 set bits, 3 is prime) 15 -> 1111 (4 set bits, 4 is not prime)
Note:
L, R will be integers L <= R in the range [1, 10^6]. R - L will be at most 10000.
解释:
求给定范围[L,R]
内,二进制表达中1的个数是素数的个数有多少个。
1.素数的判断,由于数字最大是106所以可以用20位
的二进制表达数字,那么可以用一个长度为20的数组储存该数字是否是素数。可以用动态规划来解。
是否是素数还是不要用传统的开根号法则判断了,速度太慢。
传统开根号法:
def isPrime(num):
if num<=1:
return False
for i in range(2,int(num**0.5)+1):
if num%i==0:
return False
return True
动态规划法:
N=20
isPrime=[True]*N
isPrime[0]=False
isPrime[1]=False
for i in range(2,N):
if isPrime[i]:
for j in range(i*i,N,i):
isPrime[j]=False
2.求一个数的二进制表达中1的个数,有个技巧。(当然,python的话可以直接count)
假如x是一个二进数,例如x=0xfffa(1111 1111 1111 1010),要实现去掉最低位一个1,可进行的操作是x&=(x-1)
,此时x==0xfff8(1111 1111 1111 1000) 。基于该思想,利用wile循环对(x)判断,可实现计算二进制数中所有位上1的个数。
int numOfOne(x){
int count = 0;
while(x)
{
count++;
x = x&(x-1);
}
return count;
}
3.求一个数的二进制表达中0的个数
假如x是一个二进数,例如x=0xfffa(1111 1111 1111 1010)
,要实现去掉最低位一个0,可进行的操作是x|=(x+1)
,此时x==0xfffb(1111 1111 1111 1011)
;再去掉一个0,同样,x|=(x+1)
,则x==0xffff
。如果x的2字节表示,则(x+1)
为0。基于该思想,利用wile循环对(x+1)
判断,可实现计算二进制数中所有位上0的个数。注意,x=1
时,1的高位默认有0的(注意是所有位而不是写出来的位上,因为二进制高位的0是默认不写出来的,但是不写出来不代表没有啊)。
int Grial(int x)
{
int count = 0;
while (x + 1)
{
count++;
x |= (x + 1);
}
return count;
}
python代码:
class Solution:
def countPrimeSetBits(self, L, R):
"""
:type L: int
:type R: int
:rtype: int
"""
N=20
isPrime=[True]*N
isPrime[0]=False
isPrime[1]=False
for i in range(2,N):
if isPrime[i]:
for j in range(i*i,N,i):
isPrime[j]=False
result=0
for num in range(L,R+1):
count=bin(num).count('1')
if isPrime[count]:
result+=1
return result
c++代码:
#define N 20
class Solution {
public:
int countPrimeSetBits(int L, int R) {
vector<bool>isPrime(N,true);
isPrime[0]=false;
isPrime[1]=false;
for(int i=2;i<N;i++)
{
if (isPrime[i])
{
for (int j=i*i;j<N;j+=i)
isPrime[j]=false;
}
}
int result=0;
for (int i=L;i<=R;i++)
{
int count_1=0;
int n=i;
while(n)
{
count_1+=1;
n&=(n-1);
}
if (isPrime[count_1])
result+=1;
}
return result;
}
};
总结:
判断一个数是否是素数的快速求法和求数字的二进制表达中1的个数的技巧。
python的count(‘1’)比手动计算1的个数要快很多。