剑指Offer #11 二进制中1的个数(想不到的骚操作)
題目來(lái)源:牛客網(wǎng)-劍指Offer專題
題目地址:二進(jìn)制中1的個(gè)數(shù)
題目描述
輸入一個(gè)整數(shù),輸出該數(shù)二進(jìn)制表示中1的個(gè)數(shù)。其中負(fù)數(shù)用補(bǔ)碼表示。
題目解析
對(duì)于這種涉及位運(yùn)算的題目,我們首先要了解基本的位運(yùn)算,我們可以看這篇文章:C++描述的位運(yùn)算總結(jié)
(PS:本文的圖例用的是8位的整數(shù),int有32位,畫出來(lái)也不美觀呀)
下面先給說(shuō)一種因?yàn)榇嬖谪?fù)數(shù)而錯(cuò)誤的做法:
- 先通過(guò) ‘&1’ 操作來(lái)判斷 nnn 的最低位否為1,若為1,則計(jì)數(shù)器 cntcntcnt 的值加1;
- 然后利用 ‘>>1’ 操作將 nnn 右移一位;
- 最后重復(fù)上述兩步操作,直到 nnn 的值為0,得出 cntcntcnt 的值即為該數(shù)二進(jìn)制表示中1的個(gè)數(shù)。
這種方法在 nnn 為正數(shù)的時(shí)候是沒(méi)有問(wèn)題的,因?yàn)檎龜?shù)進(jìn)行右移操作的時(shí),最低位舍棄,最高位補(bǔ)0。過(guò)程如圖所示:
但是負(fù)數(shù)進(jìn)行右移操作的時(shí),最低位舍棄,最高位的是1(過(guò)程如下圖),這樣經(jīng)過(guò)多次以后,所有數(shù)位都會(huì)變成1,進(jìn)而產(chǎn)生死循環(huán)。
下面給大家一共四種不同的正確解法:
方法一:
利用Integer內(nèi)置的toBinaryString()方法將 nnn 轉(zhuǎn)換為二進(jìn)制字符串,然后二進(jìn)制串中的0全部消掉,最后求得的字符串長(zhǎng)度就是該數(shù)二進(jìn)制表示中1的個(gè)數(shù)。
方法二:
這是對(duì)上面講到的錯(cuò)誤方法的改進(jìn),由于左移操作是最高位舍棄,最低位補(bǔ)0,我們選擇讓 nnn 不變, 對(duì) ‘&1’ 中的1進(jìn)行左移,直到移動(dòng)31位為止。
由上圖的兩種情況可以看出,當(dāng)1移動(dòng)了 iii 位之后,若 nnn 的第 iii 位為1,進(jìn)行&運(yùn)算的結(jié)果為 (1<<i)(1 << i)(1<<i),否則為0。于是,我們就可以利用他們?yōu)榕袛鄺l件來(lái)計(jì)算1的個(gè)數(shù)啦~
方法三:
這種方法是很久之前zls師兄告訴我的,沒(méi)想到今天才派上用場(chǎng)(我記憶力真好 )。
理論:nnn 和 n?1n-1n?1 進(jìn)行 &\&& 運(yùn)算可以把 nnn 的二進(jìn)制表示的右邊第一個(gè)1變成0
根據(jù)上面給的理論,我們只要知道 nnn 可以進(jìn)行多少次這樣的操作,就可以得到 nnn 的二進(jìn)制表示中1的個(gè)數(shù),下圖以n=29為例展示這個(gè)過(guò)程:
如果對(duì)上訴過(guò)程感受不深,可以手動(dòng)計(jì)算多幾組數(shù)據(jù),雖然這種方法感覺(jué)起來(lái)比較笨,但卻是理解的好辦法。能用上這種方法,面試應(yīng)該沒(méi)問(wèn)題了。
方法四:
這是在牛客網(wǎng)評(píng)論區(qū)看到做法,由Holiday_12138發(fā)表,但是ta并沒(méi)有給出具體思路,我也參悟不出來(lái),我打算以后理解了再更新這部分,也歡迎各位大佬提供解釋。(做法真的太騷了 )
如果本文對(duì)你有所幫助,要記得點(diǎn)贊哦~
總結(jié)
以上是生活随笔為你收集整理的剑指Offer #11 二进制中1的个数(想不到的骚操作)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 「软件测试基础」理论篇之软件测试概论
- 下一篇: 剑指Offer #12 数值的整数次方(