Skip to content

Conversation

@Ryotaro25
Copy link
Owner

問題へのリンク
https://leetcode.com/problems/number-of-1-bits/description/

問題文(プレミアムの場合)

備考

次に解く問題の予告

フォルダ構成
LeetCodeの問題ごとにフォルダを作成します。
フォルダ内は、step1.cpp、step2.cpp、step2_2.cpp、step3.cpp、bit_manipulation.cppとmemo.mdとなります。

memo.md内に各ステップで感じたことを追記します。

Comment on lines +46 to +54
コードが見れなくなっていたのでやり取りだけチェック
この辺りチェックしたら良さそう
https://en.wikipedia.org/wiki/Hamming_weight#Efficient_implementation
C++のもありそうなので探してみる
https://pkg.go.dev/math/bits#OnesCount
https://github.com/rihib/leetcode/pull/46

文字列に変換する方法などもある
https://github.com/Kitaken0107/GrindEasy/pull/24

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

考え方は他の解法にも似ているのですが、全てのbitをチェックする代わりに、最も右にあるbitを消すことで処理するアルゴリズムもあるようです。
Brian Kernighan’s Algorithm

int hammingWeight(unsigned int n) {
    int count = 0;
    while (n) {
        n &= (n - 1); 
        count++;
    }
    return count;
}

int num_bits = 0;
while (n > 0) {
if (n % 2 == 1) {
num_bits +=1;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+=1 のあいだにスペースを空けることをおすすめします。

int num_bits = 0;
int mask = 1;
for (int i = 0; i < 32; i++) {
if ((n & mask) != 0) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

自分なら mask 変数は使わず、

if ((n & (1 << i)) != 0) {

と書くと思います。趣味の範囲だと思います。

int hammingWeight(int n) {
int num_bits = 0;
while (n > 0) {
if (n % 2 == 1) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

num_bits += n % 2;

とも書けます。趣味の範囲だと思います。

## ステップ3
**3回書き直しやりましょう、といっているのは、不自然なところや負荷の高いところは覚えられないからです。**

## 他の解法
Copy link

@nodchip nodchip Aug 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

分割統治法による解法もあります。

n = (n & 0x55555555) + ((n >> 1) & 0x55555555);
n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
n = (n & 0x0f0f0f0f) + ((n >> 4) & 0x0f0f0f0f);
n = (n & 0x00ff00ff) + ((n >> 8) & 0x00ff00ff);
n = (n & 0x0000ffff) + ((n >> 16) & 0x0000ffff);
return n;

「ハッカーのたのしみ: 本物のプログラマはいかにして問題を解くか」に載っています。ソフトウェアエンジニアの常識には含まれていませんが、知っている人はいると思います。

if (n % 2 == 1) {
num_bits +=1;
}
n /= 2;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

個人的には

n >>= 1;

と書きます。コンパイラーで最適化オプションを付けてコンパイルすると、どちらもシフト演算の命令が生成されると思います。ぜひ確かめてみてください。

整数の割り算は遅い、ビット演算は速い、という感覚は持っておいたほうが良いと思います。以下
https://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/documents/developer/ia32.pdf
からの抜粋です。

Ice Lake and Tiger Lake

Instruction Operands Latency Reciprocal through put
DIV IDIV r32 12 6
SHR SHL SAR r,i 1 0.5

https://zenn.dev/herumi/articles/latency-throughput

CPUにおけるレイテンシ(latency)とは命令が発行されてからその実行が完了するまでの時間(クロックサイクル)です。

Intelのマニュアルによるとスループットとは同じ命令を続けて発行するときに待つclkです。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants