判斷值用二進位制表示時,某一位是否為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。
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;
}