338. 位元位計數 Counting Bits
阿新 • • 發佈:2018-12-09
給定一個非負整數 num。對於 0 ≤ i ≤ num 範圍中的每個數字 i ,計算其二進位制數中的 1 的數目並將它們作為陣列返回。
示例 1:
輸入: 2 輸出: [0,1,1]
示例 2:
輸入: 5
輸出: [0,1,1,2,1,2]
進階:
- 給出時間複雜度為O(n*sizeof(integer))的解答非常容易。但你可以線上性時間O(n)內用一趟掃描做到嗎?
- 要求演算法的空間複雜度為O(n)。
- 你能進一步完善解法嗎?要求在C++或任何其他語言中不使用任何內建函式(如 C++ 中的 __builtin_popcount)來執行此操作。
解法一:
一個一個地遍歷求解,先考慮如何求一個數n的二進位制數的1的個數,有兩種方法
1.用一個flag初始值為1,把它和n做&運算,如果不為0說明最右端是1,然後把flag左移一位,再去判斷i的倒數第二位,這樣下去直到flag移成0.
unsigned int flag = 1;
int count = 0;
while(flag)
{
if(flag & n)
{
count++;
}
flag = flag << 1;
}
2.用n & (n-1),思想是一個數n和n-1做&運算會把n的最右邊那個1變成0,一個數有多少個1就要做多少次這個運算
class Solution { public: vector<int> countBits(int num) { vector<int> ans; for(int i = 0; i <= num; ++i) { ans.push_back(bitNum(i)); } return ans; } int bitNum(int i) { int count = 0; while(i) { count++; i = i & (i - 1); } return count; } };
解法二:要在O(n)的時間複雜度完成,那肯定得用dp,也就是找規律
0 0
1 1
2 10
3 11
4 100
5 101
6 110
7 111
可以看出一個偶數和一個奇數是一對,且奇數的1個數比偶數1個數多1,並且對與對之間也有關係,一個對整體比一個對的一半多1,如111和11,110和10
那麼可以得到狀態方程ans[i] = ans[i/2]+i%2;
class Solution {
public:
vector<int> countBits(int num) {
vector<int> ans;
ans.push_back(0);
for(int i = 1; i <= num; ++i)
{
ans.push_back(ans[i>>1]+i%2);
}
return ans;
}
};
解法三:
用內建函式__builtin_popcount(n)
class Solution {
public:
vector<int> countBits(int num) {
vector<int> ans;
ans.push_back(0);
for(int i = 1; i <= num; ++i)
{
ans.push_back(__builtin_popcount(i));
}
return ans;
}
};