いちばん下の 1 を 消していき、 2 進の 1 の 数を数える
0 以上の
海外で定番の問題リスト 4 本には入っていません
問題
部屋のn にn に 1 が
nは 0 以上 4294967295 (2 の 32 乗から 1 を引いた 数) 以下です - 言語に
備わった 1 の 数を 数える 関数 ( bin(n).count、bits.OnesCountなど) は 使わずに 書いてください
入力と出力の例
例 1
13 は 2 進で 1101 です。
例 2
1024 は 2 の 10 乗で、
例 3
255 は 2 進で 1 が 8 個並びます。
面接での聞かれ方
面接では、
- 「整数の 2 進表現の 1 の
数を 返してください」 - 1 ビットずつ
見る 書き方を 見せると、 「1 の 数だけ回して 数えられますか?」と続きます - 「この
関数を 何百万回も 呼ぶなら どうしますか?」と 聞かれる こともあります
n & (n - 1) の
ヒント
まだ開いていません
付箋は 3 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3答えに近い
アルゴリズムのチートシートの「配列と文字列」に、
関わる学び
配列と
まず 考える手順
段 1
まずはn & 1 でn を 1 ビット右へずらす、を n が 0 に
段 2
n - 1 は、n のn の AND を
段 3
n = n & (n - 1) を n が 0 に
解答
Python
Python
def count_one_bits(n):
count = 0
while n != 0:
n &= n - 1
count += 1
return countJavaScript
JavaScript
function countOneBits(n) {
let count = 0;
while (n !== 0) {
n = (n & (n - 1)) >>> 0;
count++;
}
return count;
}Go
Go
func countOneBits(n uint32) int {
count := 0
for n != 0 {
n &= n - 1
count++
}
return count
}JavaScript の & は>>> 0 で 0 以上の
計算量
- 時間は、
1 の 数を k として O(k) です。 いちばん 多くても 32 回です - 使う
記憶は O(1) です - 何度も
呼ぶなら、 0 から 255 までの 1 の 数の 表を 先に 作り、 8 ビットずつ表を 引いて 足す 書き方に すると、 どの 数でも 4 回で済みます
よく ある間違い
- 符号つきの
整数を 右へずらす。 1 ビットずつ 見る 書き方で、 JavaScript の >>や、Java の 符号つきの 整数の 右ずらしを 使うと、 いちばん上の ビットが 1 の 数では 上から 1 が 入り続け、 いつまでも 0 に なりません。 符号なしで ずらします (JavaScript なら >>>) n & (n - 1)とn & (n + 1)を取り違える。 消えるのは いちばん下の 1 で、 その ためには 1 を引きます - ループの
条件を n > 0にする。 JavaScript で>>> 0を付けないと、 途中の 値が 負に なった ところで 止まってしまいます。 4294967295 では、 1 回目の AND が 負に なり、 1 を返します
解答を動かした版 Python 3.14.7Node.js 24.22.1Go 1.24.2確認日 2026年11月8日
面接での 話し方の例
書き始める
「
n - 1は、いちばん下の 1 を 0 に して、 その下を 全部 1 に した数です。 nとの AND で、いちばん下の 1 だけが 消えます。 これを nが 0 になるまで 繰り返した 回数が 1 の 数です。 時間は 1 の 数だけで、 いちばん 多くて 32 回、 記憶は O(1) です。」
書き終えたら、
「例 1 の 13 は 1101 です。
1101 & 1100 で 1100、 1100 & 1011 で 1000、 1000 & 0111 で 0 です。 3 回で 0 に なったので、 1 の 数は 3 です。」