Last Updated on 2022-03-01 by Clay
題目
Given an integern
, return an arrayans
of lengthn + 1
such that for eachi
(0 <= i <= n
),ans[i]
is the number of1
's in the binary representation ofi
.
Example 1:
Input: n = 2 Output: [0,1,1] Explanation: 0 --> 0 1 --> 1 2 --> 10
Example 2:
Input: n = 5 Output: [0,1,1,2,1,2] Explanation: 0 --> 0 1 --> 1 2 --> 10 3 --> 11 4 --> 100 5 --> 101
Constraints:
0 <= n <= 105
Follow up:
- It is very easy to come up with a solution with a runtime of
O(n log n)
. Can you do it in linear timeO(n)
and possibly in a single pass? - Can you do it without using any built-in function (i.e., like
__builtin_popcount
in C++)?
題目會輸入一個數字 n
,而我們要計算從 0
開始到 n
之間,每個數字表示成二進制時,一共會存在多少個 1
。最後回傳每個數字包含著 1
數量的陣列。
解題思路
Brute Force
直接計算從 0 開始到 n 之間的二進制轉換包含多少個 1。十進制轉換成二進制非常單純,就是在數字歸零之前,一直算出『餘數』,並把當前計算的數字除以二。
Brute Force 複雜度
由於每個數值我們都要除二直至歸零,故時間複雜度為 n*log(n)。
Time Complexity | O(n log n) |
Space Complexity | O(n) |
Brute Force C++ 範例程式碼
class Solution {
public:
vector<int> countBits(int n) {
// Init
vector<int> results({0});
// Count
for (int i=1; i<=n; ++i) {
int oneNum = 0;
int num = i;
while (num > 0) {
oneNum += num % 2;
num /= 2;
}
results.push_back(oneNum);
}
return results;
}
};
Brute Force Python 範例程式碼
class Solution:
def countBits(self, n: int) -> List[int]:
# Init
results = [0]
# Count
for n in range(1, n+1):
oneNum = 0
while n:
oneNum += n % 2
n = n // 2
results.append(oneNum)
return results
Dynamic Programming
由於題目最底下的 follow up 要求要在 O(n) 的時間複雜度內完成,所以我們應該很快地就能想像到要從前面的數值來推算後面的數值。
比方說,由於我們在計算 5 時已經計算過前面的 2,所以我們應該能夠藉由 2 的答案來推算出 5。
直接觀察範例給的解釋:
0 --> 0 1 --> 1 2 --> 10 3 --> 11 4 --> 100 5 --> 101
假設我們要計算 2 的二進制,我們可以這樣計算:
2 / 2 = 1 ... 0
1 / 2 = 0 ... 1
所以 2 的二進制為 "10"。
那麼現在假設我們要計算 5 的二進制,我們原本要使用以下土法煉鋼的方法:
5 / 2 = 2 ... 1
2 / 2 = 1 ... 0
1 / 2 = 0 ... 1
但是我們會發現,其實從第二行開始就已經是過去計算過的 2 的二進制過程了!所以我們只需要判斷原始的數字是不是奇數,如果是奇數的情況我們就拿 dp[n/2]+1
來當作 n 這個數字二進制 1 的總數;如果是偶數的情況,由於 n 一開始除 2 就是 0,所以就直接計算為 dp[n/2]
。
所以,總之我們需要建立一個 dp
表,逐步紀錄起每個數值的解答。剛好這題又要求我們回傳 0 到 n 所有數值的解答,所以就直接回傳 dp 表。
Dynamic Programming 複雜度
Time Complexity | O(n) |
Space Complexity | O(n) |
Brute Force C++ 範例程式碼
class Solution {
public:
vector<int> countBits(int n) {
// Base case
if (n == 0) return {0};
// Init
vector<int> dp(n+1, 0);
dp[1] = 1;
// Count
for (int i=2; i<=n; ++i) {
if (i % 2 == 0) {
dp[i] = dp[i/2];
}
else {
dp[i] = dp[i/2] + 1;
}
}
return dp;
}
};
Brute Force Python 範例程式碼
class Solution:
def countBits(self, n: int) -> List[int]:
# Base case
if n == 0: return [0]
# Init
dp = [0 for _ in range(n+1)]
dp[1] = 1
# Count
for i in range(2, n+1):
# Odd
if i % 2 == 1:
dp[i] = dp[i//2] + 1
# Even
else:
dp[i] = dp[i//2]
return dp