算法 | 如何把一個(gè)int型二進(jìn)制數(shù)的最右側(cè)的1提取出來?

前言

本文主要介紹如何把一個(gè)int型二進(jìn)制數(shù)的最右側(cè)的1提取出來裙品,也就是只保留該int型數(shù)對應(yīng)的二進(jìn)制最右側(cè)的1,其他的都變?yōu)?code>0俗或,并返回對應(yīng)的10進(jìn)制數(shù)字市怎。

現(xiàn)有個(gè)數(shù)num=112256700,這個(gè)num對應(yīng)的二進(jìn)制為00000110101100001110011010111100辛慰,要求把這個(gè)數(shù)的二進(jìn)制最右側(cè)的1保留区匠,其他的位置全部變?yōu)?,也就是變?yōu)?code>00000000000000000000000000000100,變更后的二進(jìn)制數(shù)對應(yīng)的十進(jìn)制為4驰弄。

思路分析

方法一

此方法為比較傳統(tǒng)的方法麻汰,也就是先把num這個(gè)是轉(zhuǎn)為二進(jìn)制形式,放到一個(gè)數(shù)組中戚篙,然后遍歷數(shù)組五鲫,找到最右側(cè)的1,記錄1的位置岔擂,然后轉(zhuǎn)成10進(jìn)制形式位喂。

此方法理解起來簡單、實(shí)現(xiàn)也簡單乱灵,但是沒有什么技術(shù)可言塑崖,也不夠優(yōu)雅,不推薦痛倚。

方法一代碼實(shí)現(xiàn)

public class Code16_FindRightOne {
    public static int getRightOne(int num) {
        int[] arr = new int[32];
        for (int i = 31; i >= 0; i--) {
            arr[i] = (num & (1 << i)) == 0 ? 0 : 1;
        }
        int res = 0;
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == 1) {
                res = i;
                break;
            }
        }
        return (int) (Math.pow(2, res));
    }
    public static void main(String[] args) {
        int rightOne = getRightOne(112256700);
        System.out.println(rightOne);
    }
}
復(fù)制代碼
image.gif

看下運(yùn)行結(jié)果為4规婆。

方法二

此方法,利用了二進(jìn)制的特性蝉稳,可以非常簡單的實(shí)現(xiàn)這個(gè)功能聋呢,先看下解決思路。

要保留左右側(cè)的1颠区,把其他位置都變?yōu)?,首先想到的是位運(yùn)算通铲,再來看下位運(yùn)算的幾個(gè)特性:

與&:兩邊都為1結(jié)果才為1毕莱,否則為0。

或|:兩邊有一個(gè)為1結(jié)果就為1颅夺,都為0時(shí)才為0朋截。

異或^:相同為0,不同為1吧黄。

我們的目的是部服,把最右側(cè)1左邊的數(shù),全部變?yōu)?拗慨,按照位運(yùn)算來看廓八,相與操作最為可能,只要把1左邊的數(shù)取反再與原來的數(shù)相與就可以了赵抢。

如果把num取反剧蹂,左邊的數(shù)是解決了,那右邊的數(shù)呢烦却?右邊的數(shù)也取反了宠叼,怎么把他還原回來呢?

先看個(gè)例子其爵,比如一個(gè)二進(jìn)制為000101000100冒冬,這個(gè)二進(jìn)制取反后為111010111011伸蚯,現(xiàn)在就差怎么把011變?yōu)?code>100了,這么一看就簡單了简烤,把011加上1不就好了剂邮?111010111011 + 1 = 111010111100。讓這兩個(gè)數(shù)再進(jìn)行相與就能保留最右側(cè)的1了乐埠。

也就是抗斤,把原來的數(shù)numnum取反加1進(jìn)行相與即可。

還記得取反加1又可以怎么表示嗎丈咐?對了瑞眼,num取反加1又可以表示為負(fù)數(shù)即-num

方法二代碼實(shí)現(xiàn)

來看下代碼吧棵逊。

public class Code17_FindRightOne {
    public static void printBinary(int num) {
        for (int i = 31; i >= 0; i--) {
            System.out.print((num & (1 << i)) == 0 ? "0" : "1");
        }
        System.out.println();
    }
    public static void main(String[] args) {
        printBinary(112256700);
        printBinary(112256700 & -112256700);
        System.out.println(112256700 & -112256700);
    }
}
復(fù)制代碼
image.gif

輸出結(jié)果:

00000110101100001110011010111100
00000000000000000000000000000100
4
復(fù)制代碼
image.gif

可以看到運(yùn)行結(jié)果和方法一是一樣的伤疙,說明方法二的代碼功能實(shí)現(xiàn)也是正確的。

為了查看方便辆影,我把原來的數(shù)以及兩個(gè)數(shù)相與后的結(jié)果的二進(jìn)制形式也打印了出來徒像。從上面結(jié)果來看,是不是把最右側(cè)的1保留下來了呢蛙讥?

總結(jié)

從上面兩個(gè)方案來看锯蛀,方法二使用位運(yùn)算比方法一簡單的太多了,僅僅簡單的一行代碼就把功能給實(shí)現(xiàn)了次慢,而且在效率方面也遠(yuǎn)比方法一高的多旁涤。

把一個(gè)數(shù)的二進(jìn)制最右側(cè)的1提取出來,在很多算法題目中會(huì)經(jīng)常遇到迫像,這里只是簡單的介紹了下如何實(shí)現(xiàn)劈愚,后面會(huì)介紹更多使用此方法的案例。

當(dāng)然實(shí)現(xiàn)方法有很多種闻妓,如果你有更好的辦法菌羽,歡迎在評論區(qū)留言交流

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市由缆,隨后出現(xiàn)的幾起案子注祖,更是在濱河造成了極大的恐慌,老刑警劉巖均唉,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件氓轰,死亡現(xiàn)場離奇詭異,居然都是意外死亡浸卦,警方通過查閱死者的電腦和手機(jī)署鸡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人靴庆,你說我怎么就攤上這事时捌。” “怎么了炉抒?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵奢讨,是天一觀的道長。 經(jīng)常有香客問我焰薄,道長拿诸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任塞茅,我火速辦了婚禮亩码,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘野瘦。我一直安慰自己描沟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布鞭光。 她就那樣靜靜地躺著吏廉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪惰许。 梳的紋絲不亂的頭發(fā)上席覆,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機(jī)與錄音汹买,去河邊找鬼娜睛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛卦睹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播方库,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼结序,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了纵潦?” 一聲冷哼從身側(cè)響起徐鹤,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎邀层,沒想到半個(gè)月后返敬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡寥院,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年劲赠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,013評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡凛澎,死狀恐怖霹肝,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情塑煎,我是刑警寧澤沫换,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站最铁,受9級特大地震影響讯赏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜冷尉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一漱挎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧网严,春花似錦识樱、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至垢村,卻和暖如春割疾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嘉栓。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工宏榕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人侵佃。 一個(gè)月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓麻昼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親馋辈。 傳聞我的和親對象是個(gè)殘疾皇子抚芦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內(nèi)容