面試題15:二進(jìn)制中1的個(gè)數(shù)

  • 輸入一個(gè)整數(shù),輸出該數(shù)二進(jìn)制表示中1的個(gè)數(shù)。其中負(fù)數(shù)用補(bǔ)碼表示。

思路一:依次右移判斷是否是奇數(shù),也就是判斷最后一位是否是1并計(jì)數(shù)。但是遇到負(fù)數(shù)多次將補(bǔ)位1,可能會造成死循環(huán)。

/**
     * 將二進(jìn)制數(shù)右移與1,如果結(jié)果等于1則最右位是1,右移一位繼續(xù)比較
     * 存在問題:右移正負(fù)值處理不同可能會出現(xiàn)死循環(huán)
     * java中有三種移位運(yùn)算符
     *
     * <<      :     左移運(yùn)算符,num << 1,相當(dāng)于num乘以2
     *
     * >>      :     右移運(yùn)算符,num >> 1,相當(dāng)于num除以2
     *
     * >>>    :     無符號右移,忽略符號位,空位都以0補(bǔ)齊
     * 本方法左右移,效率高于乘除
     * 可以使用無符號右移解決死循環(huán)問題
     */
    public int numberOf1_1(int n) {
        int count = 0;
        while (n !=0){
          if ((n & 1) == 1){
             count++;

          }
            n = n >>> 1;
        }
        return count;
    }

思路二:
第一次和1進(jìn)行與操作,后面每次將這個(gè)1乘以2,左移一次,依次比較每一位

/**
     * 常規(guī)解法
     * 分別與每個(gè)位置上的符號位相與,每次乘以2,意味著左移一位
     * @param n
     * @return
     */
    public int numberOf1_2(int n) {
        int count = 0;
        int flag = 1;
        while (flag != 0){
            if ((flag & n) != 0){
                count++;
            }
            flag = flag << 1;
        }
        return count;

    }

思路三:
我們知道如果對數(shù)進(jìn)行減一操作,二進(jìn)制方面所完成的工作是將第一位1改為0,后面有0的話,所有0改為1。所以拿他與原數(shù)與,就可以讓第一個(gè)1和后面所有數(shù)為0,知道所有位為0,找到所有的1。

/**
     * 最優(yōu)解法
     * 如果一個(gè)二進(jìn)制數(shù)減1,則第一個(gè)為1的二進(jìn)制位變?yōu)?,其后如果有0的話,則全部變?yōu)?
     * 將其與數(shù)與操作,如果不為0,則一個(gè)數(shù)為1,繼續(xù)進(jìn)行同樣的操作,一直到數(shù)為0停止
     * 那么一個(gè)整數(shù)的二進(jìn)制有多少個(gè)1,就可以進(jìn)行多少次這樣的操作
     * @param n
     * @return
     */
    public int numberOf1(int n) {
        int count = 0;
        while (n != 0){
            count++;
            n = (n-1) & n;
        }
        return count;
    }

思路四:直接尋找1,將整數(shù)調(diào)用Integer.toBinaryString(),然后比較

public int numberOf1_3(int n) {
        int count = 0;
        String binaryN = Integer.toBinaryString(n);
        char[] chars = binaryN.toCharArray();
        for (int i=0;i<chars.length;i++){
            if (chars[i] == '1'){
                count++;
            }
        }
        return count;

    }
/**
     * 判斷一個(gè)整數(shù)是不是2的正整數(shù)次方。
     * 直接統(tǒng)計(jì)1的個(gè)數(shù),看其是否等于1
     */
    public boolean isExponOf2(int n) {
        return numberOf1(n) == 1;
    }

    /**
     * 輸入兩個(gè)整數(shù)m和n,計(jì)算需要改變m的二進(jìn)制表示中的幾位才能得到n。
     * 比如10的二進(jìn)制是1010,13的二進(jìn)制是1101,則需要改變3次。
     * @param m 一個(gè)整數(shù)
     * @param n 另一個(gè)整數(shù)
     * @return 需要改變的位數(shù)
     */
    public int bitNumNeedsToBeChanged(int m, int n) {
        /**
         * 關(guān)鍵操作:先做異或操作
         * 如果不同則為1,相同為0
         * & 與操作,都為1才為1
         * | 或操作,都為0時(shí)才為0
         */

        return numberOf1(m ^ n);
    }

小技巧:
很多題型可以通過統(tǒng)計(jì)二進(jìn)制中1的個(gè)數(shù)來解決。例如求是否是2的整數(shù)次冪,兩個(gè)整數(shù)需要改變二進(jìn)制幾位才能得到另一個(gè)數(shù)就是統(tǒng)計(jì)異或操作后1的個(gè)數(shù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容