Given two integers L
and R
, 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 1
s present when written in binary. For example, 21
written in binary is 10101
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 is prime) 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 integersL <= R
in the range[1, 10^6]
.R - L
will be at most 10000.
這道題給了我們一個整數范圍[L, R],讓我們統計其中有多個整數,其二進制表示中非零位個數為質數。參考題目中的例子不難理解題意,那么博主最先想到的就是暴力搜索啊,畢竟是到Easy題嘛,可能不需要太多的技巧。我們遍歷整數范圍[L, R]中的每一個數字,然后先統計出所有非零位個數cnt,通過和1相與,再右移一位的方式。然后就是來判斷這個cnt是否是質數,判斷的方法就是就是從其平方開始,一個一個的除,如果一直到2都沒有約數,那么就是質數啦,結果res累加1,參見代碼如下:
解法一:
class Solution { public: int countPrimeSetBits(int L, int R) { int res = 0; for (int i = L; i <= R; ++i) { int t = i, cnt = 0; while (t > 0) { if (t & 1 == 1) ++cnt; t >>= 1; } bool succ = true; for (int j = sqrt(cnt); j > 1; --j) { if (cnt % j == 0) { succ = false; break; } } if (succ && cnt != 1) ++res; } return res; } };
好,下面我們來優化一下上面的解法,由於題目中給了數的大小范圍 R <= 106 < 220,那么我們統計出來的非零位個數cnt只需要檢測是否是20以內的質數即可,所以我們將20以內的質數都放入一個HashSet中,然后統計出來cnt后,直接在HashSet中查找有沒有即可,參見代碼如下:
解法二:
class Solution { public: int countPrimeSetBits(int L, int R) { int res = 0; unordered_set<int> primes{2, 3, 5, 7, 11, 13, 17, 19}; for (int i = L; i <= R; ++i) { int cnt = 0; for (int j = i; j > 0; j >>= 1) { cnt += j & 1; } res += primes.count(cnt); } return res; } };
下面這種寫法就更簡潔啦,直接使用了C++的內置函數__builtin_popcount來快速的求出非零位的個數cnt,然后又利用到了20以內的數,只要不能被2和3的一定是質數,又可以快速判斷了質數了,參見代碼如下:
解法三:
class Solution { public: int countPrimeSetBits(int L, int R) { int res = 0; for (int i = L; i <= R; ++i) { int cnt = __builtin_popcount(i); res += cnt < 4 ? cnt > 1 : (cnt % 2 && cnt % 3); } return res; } };
類似題目:
參考資料: