1. 程式人生 > >bitCount 求二進位制數中1的個數

bitCount 求二進位制數中1的個數

解法一:

對於一個正整數如果是偶數,該數的二進位制數的最後一位是 0 ,反之若是奇數,則該數的二進位制數的最後一位是 1 。因此,可以考慮利用位移、判斷奇偶來實現。

Java程式碼  收藏程式碼
  1. public int bitCount(int x){  
  2.     int count = 0;  
  3.     while(x!=0){  
  4.      if(x%2!=0){  //判斷奇偶數  
  5.         count++;  
  6.      }  
  7.       x = x>>>1;  
  8.     }  
  9.     return count;  
  10.  }  

解法二:

知道了位移操作同樣可以判斷奇偶,且效率高於除法操作(“ % ”求餘操作最後還是化為除法操作)那就可以用位移來代替上的求餘運算。

      因為 x & 1 的結果為 1 或 0 ,為 1 的時候 count+=1 ,為 0 的時候 count+=0

則:

     If(x&1==1){

         count++;

     }

可簡化為: count+ = x&1;

Java程式碼  收藏程式碼
  1. public int bitCount2(int x){  
  2.         int count = 0;  
  3.         while(x!=0){  
  4.             count+ = x&1;  
  5.             x = x>>>1;  
  6.         }  
  7.         return count;  
  8.   }  
 

解法三:

正整數的二進位制數最高位為 0 ,負整數和二進位制數最高們為 1 ,則可利用左移、判斷正負來實現 1 的個數的計算。

Java程式碼  收藏程式碼
  1. public int bitCount3(int x){  
  2.       int count = 0;  
  3.       while(x!=0){  
  4.          if(x<0){  
  5.             count++;  
  6.          }  
  7.          x = x<<1;  
  8.       }  
  9.       return count;  
  10. }  

解法四:

前面的三種解法,運算的次數為二進位制數的位數,時間複雜度仍為 O(log2 v) ,然而我們要計算 1 的個數,若讓演算法的運算次數只與“ 1 ”的個數有關,那複雜度就能進一步降低。

思想: x & (x-1) 可以消去 x 二進位制數的最後一位 1

Java程式碼  收藏程式碼
  1. public int bitCount4( int x )  
  2. {  
  3.        int count = 0;  
  4.        while ( x != 0 )  
  5.        {  
  6.          x &= x - 1;  
  7.          count++;  
  8.        }  
  9.        return count;  

解法五:

JAVA 的 JDK 庫裡 Integer 有個 bitCount 方法,其程式碼是這樣實現的

Java程式碼  收藏程式碼
  1. private int pop(int x)  
  2.  {  
  3.        x = x - ((x >> 1) & 0x55555555);  
  4.        x = (x & 0x33333333) + ((x >> 2) & 0x33333333);  
  5.        x = (x + (x >> 4)) & 0x0F0F0F0F;  
  6.        x = x + (x >> 8);  
  7.        x = x + (x >> 16);  
  8.        return x & 0x0000003F;  
  9.    }  
 

==============================================================

二分法,兩兩一組相加,之後四個四個一組相加,接著八個八個,最後就得到各位之和了。

第一行是計算每兩位中的 1 的個數 , 並且用該對應的兩位來儲存這個個數 ,
如 : 01101100 -> 01011000 , 即先把前者每兩位分段 01 10 11 00 , 分別有 1 1 2 0 個 1, 用兩位二進位制數表示為 01 01 10 00, 合起來為 01011000.

第二行是計算每四位中的 1 的個數 , 並且用該對應的四位來儲存這個個數 .
如 : 01101100 經過第一行計算後得 01011000 , 然後把 01011000 每四位分段成 0101 1000 , 段內移位相加 : 前段01+01 =10 , 後段 10+00=10, 分別用四位二進位制數表示為 0010 0010, 合起來為 00100010 .
下面的各行以此類推 , 分別計算每 8 位 ,16 位 ,32 位中的 1 的個數 .
將 0x55555555, 0x33333333, 0x0f0f0f0f 寫成二進位制數的形式就容易明白了 .

解法六:

HAKMEM 演算法

Java程式碼  收藏程式碼
  1. private int pop2(int x) {  
  2.        int n;     
  3.        n = (x >> 1) & 033333333333;     
  4.        x = x - n;    
  5.        n = (n >> 1) & 033333333333;    
  6.        x = x - n;     
  7.        x = (x + (x >> 3)) & 030707070707;    
  8.        x = x%63;   
  9.        return x;    
  10.      }  

首先是將二進位制各位三個一組,求出每組中 1 的個數,然後相鄰兩組歸併,得到六個一組的 1 的個數,最後很巧妙的用除 63 取餘得到了結果。

因為 2^6 = 64 ,也就是說  x_0 + x_1 * 64 + x_2 * 64 * 64 = x_0 + x_1 + x_2 (mod 63) ,這裡的等號表示同餘

參考資料:

4. gurmeet.net/puzzles/fast-bit-counting-routines/

8. http://mindprod.com/jgloss/bitcount.html


相關推薦

bitCount 二進位制1個數

解法一: 對於一個正整數如果是偶數,該數的二進位制數的最後一位是 0 ,反之若是奇數,則該數的二進位制數的最後一位是 1 。因此,可以考慮利用位移、判斷奇偶來實現。 Java程式碼   public int bitCount(int x){      int cou

演算法題:N!末尾0的個數二進位制1個數

1、給定一個整數,那麼N的階乘N!末尾有多少個0呢? 解題思路:N!=K*10^M,M的值即為N!末尾0的個數。又10^M=(2^M)*(5^M),因為一個數進行質因數分解後,2出現的概率比5大得多。所以只有計算出1到N包含多少個5的因子 public class demo2 {

程式設計之美3:二進位制1個數

1: int Count(BYTE v) { int num = 0; while (v) { if (v % 2 == 1) { num++; } v = v / 2; }

演算法-二進位制1個數

問題描述 任意給定一個32位無符號整數n,求n的二進位制表示中1的個數,比如n = 5(0101)時,返回2,n = 15(1111)時,返回4 這也是一道比較經典的題目了,相信不少人面試的時候可能遇到過這道題吧,下面介紹了幾種方法來實現這道題,相信很多人可能見過下

關於Java的一道題:"二進位制1個數"的解法整理

package com.accp; /**  * 求二進位制數中1的個數  *  * @author Administrator  *  */ public class BinaryConvers

二進位制1個數

第一種最常見的解法: 原理是:採用C語言十進位制轉換成二進位制的方法去解題 程式程式碼如下: #include "Count.h" int Count(char b) { int number = 0; while (b) {

Java實現一個整數的二進位制1個數

這題還是筆試的時候遇到的,當時沒有想太多,直接用了最為直接的移位相加的方法,雖然可以得出結果,但是程式效率低。 後來發現使用n=n&(n-1)的方法,效率會更高,先上程式碼。 <span

如何一個整數的二進位制1個數

1、使用位移 while (temp>0) { if ( (temp & 1) == 1 ) { //temp

一個int型二進位制1個數

#include <stdio.h> int main(int argc, const char *argv[]) {     int i = 0;     int a = 0;     int n = 0;     printf("please enter a int:");     scanf

[華為機試練習題]45.二進位制1個數

題目 描述: 題目標題: 求某二進位制數中1的個數。 給定一個unsigned int型的正整數,求其二進位制表示中“1”的個數,要求演算法的執行效率儘可能地高。 詳細描述: 原型: i

Java計算二進位制1個數

前言 逐位法 查表法 Brian Kernighan法 分治法 Hamming Weight法 Hamming Weight優化法 Hamming Weight乘法優化法 MIT HAKMEM 169演算法 江峰求一演算法 分治法

十進位制轉化為二進位制1個數

#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<math.h> int solve(int n) { int ans = 0; while (n) ans += n &a

統計二進位制1個數

思路:定義n表示1的個數,一個二進位制數按位遍歷一遍,並且每一位按位與1,結果為1,則n加1,輸出n即為結果。 程式碼: #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.

二進位制1個數

題目 輸入一個整數,輸出該數二進位制數1的個數 import java.util.Scanner; public class Main { public static void main(S

LeetCode 338. Counting Bits(計算二進位制1的位數)

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 repre

LeetCode 231. Power of Two (演算法,計算二進位制1的位數)

Given an integer, write a function to determine if it is a power of two. 輸入一個數,判斷其是否為2的冪。 思路:可以按照326題的思路,用換底公式計算。也可以根據2進位制的特點,2的冪一定是最高位是1

【面試題】劍指offer10--個數二進位制1個數

求一個數二進位制數中的個數 第一種方法:模除法 程式碼如下: //Q:請實現一個函式,輸入一個整數,輸出該數二進位制中的 //1的個數。例如:把9表示成二進位制是1001,有2位是1.因此,如果輸入

二進位制返回1個數的幾種方法

方法一:採用先模2再除2的方法,例如13模2結果是1,這個1就是二進位制數中最後一個1,再除以2去除這一個位1,以此往復循化,當二進位制數全是零的時候就沒有1了,迴圈結束。但是此方法只適用於正數。 int main() { int num = 13;//1101 int cou

利用異或判斷二進位制1個數的奇偶性

文章目錄 異或壓縮奇偶性資訊 一位一位地異或 利用二叉樹思想異或 關於有符號數和算術右移 利用x &= x-1求二進位制1個數 利用邏輯右移求二進位制1個數 兩個二進位制數異或後結果的1個數的奇偶性 異或

計算一個二進位制數字“1”的個數(位運算)

int numberOfOne( unsigned value ) { int count; for( count = 0; value != 0; value >>= 1 ) if( ( value & 1 ) != 0 )//如果最低位是1,就增加計數器的