問題描述
Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1's in their binary representation and return them as an array.
Follow up:
- It is very easy to come up with a solution with run time O(n*sizeof(integer)). But can you do it in linear time O(n) /possibly in a single pass?
- Space complexity should be O(n).
- Can you do it like a boss? Do it without using any builtin function like __builtin_popcount in c++ or in any other language.
給定一個非負整數num,對於0≤i≤num範圍內的每個數字i,計算其二進制表示中的1的個數,並將它們作爲數組返回。
跟進:
- 用運行時O(n*sizeof(integer))提出一個解決方案是非常容易的。但你能在線性時間O(n)內完成嗎?
- 空間複雜度應該是O(n)。
- 你能像老闆那樣做嗎?在c++或其他任何語言中都不需要使用任何內建函數,如_builtin_popcount。
輸入: 2
輸出: [0,1,1]
輸入: 5
輸出: [0,1,1,2,1,2]
Python 實現
實現一:轉化成二進制數後數 ‘1’ 的個數。不用說,這是一個很耗內存的實現方法,每次轉換成二進制數時都需要使用新的內存。
class Solution(object):
def countBits(self, num):
"""
:type num: int
:rtype: List[int]
"""
bitCnt = [0]
for n in range(1,num+1):
bitCnt.append(format(n,'b').count('1'))
return bitCnt
實現二:尋找規律。二進制數與 2 的 n 次方有很密切的關係,那麼我們可以觀察一下當入參 num 爲 2 的 n 次方時,所得的結果有什麼規律:
[0]
[0, 1]
[0, 1, 1, 2]
[0, 1, 1, 2, 1, 2, 2, 3]
[0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4]
...
沒看出來?給個提示:看看每一個數組中,新增的後半部分元素與前半部分有什麼關係。
沒錯,後半部分的每一個元素相當於前半部分每個元素加一後的結果。
但是這個方法存在一個缺點就是,當入參 num 較大時,一個極端情況 num = 2^n + 1,這樣我們就需要計算到 2^(n+1),但後面的 2^n - 1 個數都會被拋棄,因此存在着運算資源的浪費。
class Solution(object):
def countBits(self, num):
"""
:type num: int
:rtype: List[int]
"""
bitCnt = [0]
while len(bitCnt) < num+1:
bitCnt.extend([i+1 for i in bitCnt])
return bitCnt[:num+1]
實現三:動態規劃。
分析相鄰兩個整數在二進制表示下的關係。如果 n 是奇數,那麼其最低比特位爲1,則 n>>1 (表示 n 右移一位)出現 1 的個數再加 1 就是 n 出現 1 的個數(奇數右移一位會丟失最低位的 1);如果 n 是偶數,則右移一位後,出現 1 的個數不變。其中,我們所要知道的 n>>1 出現 1 的個數,必然在前面計算已經得到,所以這一題可以使用動態規劃來解決。
class Solution(object):
def countBits(self, num):
"""
:type num: int
:rtype: List[int]
"""
bitCnt = [0]*(num+1)
for i in range(1, num+1):
bitCnt[i] = bitCnt[i>>1] + i%2
return bitCnt