1. 程式人生 > >【Leetcode】338. Bit位計數

【Leetcode】338. Bit位計數

一個 ems 進制數 tco rip 題目 res AS 都是

每次刷leetcode都有一種發現新大陸的感覺。

題目鏈接:https://leetcode-cn.com/problems/counting-bits/description/

給定一個非負整數 num。 對於範圍 0 ≤ i ≤ num 中的每個數字 i ,計算其二進制數中的1的數目並將它們作為數組返回。

示例:
比如給定 num = 5 ,應該返回 [0,1,1,2,1,2].

進階:

    • 給出時間復雜度為O(n * sizeof(integer)) 的解答非常容易。 但是你可以在線性時間O(n)內用一次遍歷做到嗎?
    • 要求算法的空間復雜度為O(n)。
    • 你能進一步完善解法嗎? 在c ++或任何其他語言中不使用任何內置函數(如c++裏的 __builtin_popcount)來執行此操作。

0    0000    0
-------------
1    0001    1
-------------
2    0010    1
3    0011    2
-------------
4    0100    1
5    0101    2
6    0110    2
7    0111    3
-------------
8    1000    1
9    1001    2
10   1010    2
11   1011    3
12   1100    2
13   1101    3
14   1110    3
15   1111    4

找規律,以分割線為界限。比如4-7。4,5和2,3相同,但是6,7卻是2,3 加 1. 而8-15也符合類似的規則。可以用這個規律寫下代碼。

大神解法:

1 public int[] countBits(int num) {
2     int[] f = new int[num + 1];
3     for (int i=1; i<=num; i++) 
4         f[i] = f[i >> 1] + (i & 1);
5     return f;
6 }

下面這種方法就更加巧妙了,巧妙的利用了i&(i - 1), 這個本來是用來判斷一個數是否是2的指數的快捷方法,比如8,二進制位1000, 那麽8&(8-1)為0,只要為0就是2的指數, 那麽我們現在來看一下0到15的數字和其對應的i&(i - 1)值:

i    bin       ‘1‘    i&(i-1)
0    0000    0
-----------------------
1    0001    1    0000
-----------------------
2    0010    1    0000
3    0011    2    0010
-----------------------
4    0100    1    0000
5    0101    2    0100
6    0110    2    0100
7    0111    3    0110
-----------------------
8    1000    1    0000
9    1001    2    1000
10   1010    2    1000
11   1011    3    1010
12   1100    2    1000
13   1101    3    1100
14   1110    3    1100
15   1111    4    1110

我們可以發現每個i值都是i&(i-1)對應的值加1,這樣我們就可以寫出代碼如下:

 1 class Solution {
 2 public:
 3     vector<int> countBits(int num) {
 4         vector<int> res(num + 1, 0);
 5         for (int i = 1; i <= num; ++i) {
 6             res[i] = res[i & (i - 1)] + 1;
 7         }
 8         return res;
 9     }
10 };

唉,都市人才啊。怎麽想到的

【Leetcode】338. Bit位計數