位運算:二進位制中1的個數
阿新 • • 發佈:2019-01-06
題目:請實現一個函式,輸入一個整數,輸出該數二進位制表示中1的個數。例如把9表示成二進位制是1001,有2位是1。因此輸出2.
1.可能引起死迴圈的解法:
一個基本思路:先判斷整數二進位制表示中最右邊一位是不是1。接著把輸入的整數右移一位,此時原來處於從右邊數起的第二位被移到最右邊了,再判斷是不是1。這樣每次移動1位,直到整個整數變成0為止。判斷最右邊是不是1,只要把整數和1做位與運算看結果是不是0就直到了。1除了最右邊一位之外所有位都是0.如果一個整數與1做與運算的結果是1,表示該整數最右邊一位是1,否則是0. 程式碼如下:
public static int numberOfOne1(int num){
int count = 0;
int rs=0;
while(num!=0){
if((rs =num & 1)!=0)
count++;
num = num >> 1;
}
return count;
}
但是當輸入一個負數時,移位後,最高位仍然為1,如果一直做右移運算,這個數字會變成0xffffffff, 進入死迴圈。
2.常規解法
為了避免死迴圈,我們可以不右移輸入的數字n. 首先把n和1做與運算,判斷n的最低位是不是1.接著把1左移一位得到2,再和n做與運算,判斷n的次低位是不是1…這樣反覆左移,每次都能判斷n的其中一位是不是1.基於這種思路,程式碼如下:
public static int numberOfOne2(int num){
int count1 = 0;
int flag = 1;
int rs = 0;
int count2 = 0;
while(count2<Integer.SIZE){
if((rs=num&flag)!=0)
count1++;
flag = flag << 1;
count2++;
}
return count1;
}
迴圈次數等於整數二進位制的位數。
3.驚喜解法
思路: 如果把一個整數減去1,再和 原整數做與運算,會把該整數最右邊一個1變成0.如二進位制1100,減去1後變為1011,1100和1011做位與運算是1000.把1100最右邊的1變成了0
那麼一個整數的二進位制表示中有多少個1,就可以進行多少次這樣的操作。程式碼如下:
public static int numberOfOne3(int num){
int count = 0;
while(num!=0){
num = (num-1) & num;
count++;
}
return count;
}
判斷一個整數是不是2的整數次方。一個整數如果是2的整數次方,那麼它的二進位制表示中有且只有一位是1,
而其他所有位是0.把這個整數減去1之後再和它自己做與運算,這個整數中唯一的1就會變成0.
public static boolean is2pow(int num){
return (num & (num-1))==0;
}
輸入兩個整數m和n,計算需要改變m的二進位制表示中的多少位才能得到n.比如10的二進位制表示為1010,13的
二進位制表示為1101,需要改變1010中的3位才能得到1101. 分兩步解決:第一步求這兩個數的異或,第二步統計
異或結果中1的個數
public static int diff(int num1, int num2){
int num = num1 ^ num2;
int count = numberOfOne3(num);
return count;
}
把一個整數減去1之後再和原來的整數做位與運算,得到的結果相當於是把整數的二進位制表示中的最右邊一個1變成0.很多二進位制的為題都可以用這個
思路解決