1. 程式人生 > 其它 >判斷值用二進位制表示時,某一位是否為1或找出所有的1

判斷值用二進位制表示時,某一位是否為1或找出所有的1

技術標籤:C++資料結構與演算法c++leetcode程式語言資料結構演算法

判斷值用二進位制表示時,某一位是否為1或找出所有的1

刷LeetCode題和看各類思路總結而來的

方法

方法一:位與運算 num & 1; num = num >> 1;
方法二:取模運算 N % 2 ==1; N /= 2;

1. 方法一

位與運算&
性質:
都是1返回1,否則返回是0。

常見作用:
①判斷某位值是否為1。
方法:將要檢測的那位置為1,其餘為0。該數和被檢測物件進行位與,那麼無論其他位置值是不是1,結果都是0,而只有要檢測的那位置在被檢測物件裡為1的時候,結果才不為0,否則為0。

比如二進位制數:1010檢測第1位(右邊開始第0個)是否為1,則可以用1010 & 0010 != 0 來判斷。

2. 方法二
取模運算 N % 2 ==1; N /= 2;

例題

1. 方法一:
主要來自於:
思路

例題:
給定一個32位非負整數n,可正、可0。返回該整數二進位制表達中1的個數。

思路一:檢查有幾個1[簡單思路]。

int count1(int n)
{
    unsigned int num = (unsigned)n;
    int res = 0;
    while(num != 0)
    {
        res += num & 1;
        num =
num >> 1; } return res; }

整數n每次進行無符號右移一位,檢查最右邊的bit是否為1來進行統計即可。
其中,res += num & 1; 利用了位與的性質實現了常用的作用,即,判斷某位值是否為1。這裡是為了判斷最右側位是否為1。是1,則返回1,否則為0。
而num = num >> 1; 是為了對num一步一步進行遍歷,從右到左,直到num已經為0,即全部的位上面都是0,就不需要進行位與和判斷操作了。
而顯然該方法最壞情況下要進行32次迴圈,接著進行優化。

接下來介紹兩個迴圈次數只與1的個數有關的解法
思路二:

int count3
(int n) { int res = 0; while(n != 0) { n = n & (n-1); res++; } return res; }

其中,n = n & (n-1)這也是移除最右側1的過程。例如: n = 01000100, n-1 = 01000011, n & (n-1) = 01000000。

思路三:

int count2(int n)
{
    int res = 0;
    while(n != 0)
    {
        n -= n & (~n + 1);
        res++;
    }
    return res;
}

其中,每次進行n -= n & (~n + 1)操作時就是移除最右邊1的過程。n & (~n + 1)的含義就是得到n中最右邊的1。例如,n = 01000100, n & (~n + 1) = 00000100, n - n & (~n + 1) = 01000000。其中~n是位求反。

2. 方法2:
50. Pow(x, n)
題解中:
在這裡插入圖片描述
所以需要判斷77以二進位制表達時,其中的所有的1:
因此,N % 2 == 1 就是判斷N 二進位制表示的最低位是否為 1;
N /= 2; 就是繼續右移一位,因為N /= 2;N >> 1;在無符號情況下是等價的 (強調無符號是因為位運算在有符號情況下可能會有其他情況)

        while (N > 0) {
            if (N % 2 == 1) {
                // 如果 N 二進位制表示的最低位為 1,那麼需要計入貢獻
                ans *= x_contribute;
            }
            // 將貢獻不斷地平方
            x_contribute *= x_contribute;
            // 捨棄 N 二進位制表示的最低位,這樣我們每次只要判斷最低位即可
            N /= 2;
        }