劍指offer_面試題10_二進制中1的個數(位運算)

題目:請實現一個函數,輸入一個整數,輸出該數二進制表示中 1 的個數。例如把 9 表示成二進制 1001,有 2 個 1。因此如果輸入9,該函數輸出2。 

位運算基本概念:

五種位運算:與(&)、或(|)、異或、左移 和 右移。

ps:其中 異或(運算符 ^),1 ^ 0 = 1;   1 ^ 1 = 0;  0 ^ 0 = 0; 0 ^ 1 = 1;  即 相同爲假,不同爲真。

左移運算符 <<,m << n,表示將 m 向左移動 n 位,並且 最左邊的 n 位被丟棄,同時最右邊補上 n 個 0。比如

00001010 << 2 = 001010 00;   // 最左邊兩位被丟棄,最右邊兩位 補 0;

10001010 << 3 = 01010 000

右移運算符 >>,m >> n,表示將 m 向右移動 n 位,並且 最右邊的 n 位被丟棄。但最左邊的補植比較複雜,分補0 和 補1,比如

00001010 >> 2 = 00 000010;   // 無符號數,最右邊兩位被捨棄,最左邊兩位 補0;

10001010 >> 3 = 111 10001;   // 有符號數,最高位爲1,表示是負數,因此 最右邊三位被捨棄,最左邊三位 補1;

常規解法:(不要用 右移運算來求解,因爲若是 有符號數,會補1)

/*關鍵值flag,通過左移運算來求解,多少位循環多少次*/
int Numberof1(int n)
{
    int count = 0;
    unsigned int flag = 1;
    while(flag)
    { 
        if(n & flag)     /** 0000 0001 ==> 0000 0010 ==> 0000 0100 ==> ...通過值 1 的那一位的移動(並且進行與運算)來判斷 n 中 1 的個數 */
            count++;
        flag = flag << 1;
    }
    return count;
}


驚喜解法:

將一個整數減去1,再和原整數做與運算,會把該整數最右邊一個1變成0。

/** n & (n - 1) 操作會將 n 最右邊的一個 1 變爲0,可以通過舉例來理解*/
int Numberof2(int n)
{
    int count = 0;
    while(n)
    {
        count++;
        n = n & (n - 1);
    }
    return count;
}

相關題目:

1、用一條語句判斷一個整數是不是 2 的整數次方。

答:若一個數是 2 的整數次方,那其二進制表示中,有且只有一位是 1。使用 n&(n-1)

2、輸入兩個整數 m 和 n,計算需要改變 m 的二進制表示中的多少位才能得到 n。

答:舉例,使用 異或運算,統計異或結果中 1 的個數。

/*點滴積累,我的一小步O(∩_∩)O~*/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章