剣指offer---バイナリ中1の個数C++題解
2457 ワード
C++は、実はポイントでビット演算と言っているので、まずビット演算を利用することを考えるべきです.
ビットと(&)演算子
その名の通り、操作数のバイナリを演算します.例えば2&1で、結果は0です.バイナリ計算10&01は00ですから.
n&n-1は何をしましたか
例を挙げると,n=10,nのバイナリが1010,n−1すなわち9,バイナリが1001であると仮定すると,1010&1001を用いた結果,1000となり,元のn=1010に比べて右から最初の1がなくなったことが分かった.
分析してみると、n-1のバイナリ値は必ず元のバイナリ値の右から最初の1を0にし、この1の右のすべての0が1になり、さらにビットと演算を行うと、nバイナリの中で右から最初の1を取り除くと同時に、n-1バイナリが増えたばかりの1も0になるので、n&n-1に比べて右から最初の1が少なくなります.
次のように計算します.
ループごとに右端の1が消去され、すべての1が消去されるまで消去されるので、変数をカウントするだけでnバイナリの1の個数を統計することができます.
コードは次のとおりです.
ビットと(&)演算子
その名の通り、操作数のバイナリを演算します.例えば2&1で、結果は0です.バイナリ計算10&01は00ですから.
n&n-1は何をしましたか
例を挙げると,n=10,nのバイナリが1010,n−1すなわち9,バイナリが1001であると仮定すると,1010&1001を用いた結果,1000となり,元のn=1010に比べて右から最初の1がなくなったことが分かった.
分析してみると、n-1のバイナリ値は必ず元のバイナリ値の右から最初の1を0にし、この1の右のすべての0が1になり、さらにビットと演算を行うと、nバイナリの中で右から最初の1を取り除くと同時に、n-1バイナリが増えたばかりの1も0になるので、n&n-1に比べて右から最初の1が少なくなります.
次のように計算します.
while (n) {
n = n & n - 1;
}
ループごとに右端の1が消去され、すべての1が消去されるまで消去されるので、変数をカウントするだけでnバイナリの1の個数を統計することができます.
コードは次のとおりです.
class Solution {
public:
int NumberOf1(int n) {
int cnt = 0;
while (n) {
cnt++;
n = n & (n-1);
}
return cnt;
}
};