最近做LeetCode上面的題目,發現很多題目都用到了n&(n-1)。感覺真是神通廣大,下面就目前所看到的一些用途總結一下:
1,求一個int類型數是否為2的冪
當n=4時,二進制為:0100
n-1=3,二進制為:0011
則:n&(n-1)==0
當n=8時,為1000
n-1=7,為0111
則n&(n-1)==0
再舉個反例:當n=5,為0101
n-1為0100
則n&(n-1)=0100=4!=0
從上面我們可以看出,凡是2的冪,均是二進制數的某一高位為1,且僅此高位為1,比如4,0100;8,1000。那么它的n-1就變成了1所處的高位變成0,剩余低位變成1,如4-1,0011,8-1,0111,那么n&(n-1)必為0
也就是n&(n-1)==0
2,一個數的二進制中有多少位為1
while(n>0){
count++;
n = n&(n-1);
}
這個原理有點類似於2的冪,大家可以自己動手試試,文字的解釋永遠無法戰勝自己的親身實踐
3,一個數是否為4的冪
一個數是4的冪,那么必然是2的冪,反之,則不然
那么首先確定條件n&(n-1)==0,確定出該數是否為2的冪,這就找到了一項必要條件
剛才說了一個數是2的冪卻不一定是4的冪,比如2,8,32等這些都是2的級數次方
但是,我們可以發現,2的偶數次方,比如2^0=1,2^2=4,2^4=16,這些數減去1,都能被3整除,而2的奇數次方的數減去1之后無法被3整除,不信可以試試
這樣的話,我們就可以很容易找到4的冪的充要條件,即 n>0 && ((n&(n-1))==0) && ((n-1)%3==0)
4,接下來還有一些可以用到符號&運算的例子,比如求一個數32位二進制的倒序
int result =0;
for(int i=0;i<32;i++){
result<<=1;//result先左移一位,低位補0
result = result+(n&1);
n>>=1;//n右移一位,高位補0
}
5,將一個數表示為16進制,並返回相應字符串
if(n==0) return "0";
String result ="";
String[] map={"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};
while(n!=0){
result = map[n&15]+result;
n>>=4;
}
好了,暫時就這么多,以后遇到了再補上。