面試題56_I_數(shù)組中數(shù)字出現(xiàn)的次數(shù)

題目描述

一個(gè)整型數(shù)組 nums 里除兩個(gè)數(shù)字之外褂始,其他數(shù)字都出現(xiàn)了兩次鲜结。請(qǐng)寫程序找出這兩個(gè)只出現(xiàn)一次的數(shù)字普泡。要求時(shí)間復(fù)雜度是O(n),空間復(fù)雜度是O(1)咙边。

題解一

先將數(shù)組排序猜煮,然后再找出現(xiàn)一次的數(shù)字是比較簡(jiǎn)單的次员。

時(shí)間復(fù)雜度為O(nlogn),空間復(fù)雜度為O(1)王带。比較簡(jiǎn)單翠肘,代碼省略。

題解二

還有一種想法是以空間換時(shí)間辫秧,使用一個(gè)哈希表來記錄數(shù)組中每個(gè)數(shù)字出現(xiàn)的次數(shù),最終可以得到兩個(gè)只出現(xiàn)一次的數(shù)字被丧。

時(shí)間復(fù)雜度為O(n)盟戏,空間復(fù)雜度為O(n)。比較簡(jiǎn)單甥桂,代碼省略柿究。

題解三

重頭戲來了,我們可以在時(shí)間復(fù)雜度為O(n)的情況下黄选,將空間復(fù)雜度降低至O(1)蝇摸。如果將這道題改為數(shù)組中只有一個(gè)數(shù)字只出現(xiàn)一次,那么問題就簡(jiǎn)單了办陷。我們可以利用異或運(yùn)算(相同為0貌夕,不同為1)的性質(zhì):

  1. 任何一個(gè)數(shù)字異或它自己都等于0。
  2. 異或運(yùn)算具有交換律民镜。

因此啡专,如果我們依次遍歷異或數(shù)組中的每個(gè)數(shù)字,那么最終出現(xiàn)的結(jié)果就是那個(gè)只出現(xiàn)一次的數(shù)字(因?yàn)槠渌嗤臄?shù)字進(jìn)行異或運(yùn)算之后都是0制圈,全部抵消了)们童。

但是由于這道題中有兩個(gè)數(shù)字只出現(xiàn)一次,所以問題會(huì)復(fù)雜一點(diǎn)鲸鹦,但是我們依舊可以將它化解為一個(gè)數(shù)字的情形慧库。只要將原數(shù)組拆成兩個(gè)數(shù)組,每個(gè)數(shù)組都包含一個(gè)只出現(xiàn)一次的數(shù)字即可馋嗜。

我們還是從頭到尾一次遍歷異或數(shù)組中的每個(gè)數(shù)字齐板,最終會(huì)得到那兩個(gè)只出現(xiàn)一次的數(shù)字的異或結(jié)果。而這個(gè)結(jié)果的二進(jìn)制表示中至少有一位為1葛菇,假設(shè)我們?cè)诮Y(jié)果中找到第一個(gè)為1的位的位置覆积,記為index,那么就可以對(duì)于所有數(shù)字按照這個(gè)位是否為1劃分為兩部分熟呛。

建立兩個(gè)數(shù)組宽档,分別保存拆成兩個(gè)數(shù)組之后的結(jié)果。因?yàn)槟莾蓚€(gè)只出現(xiàn)一次的數(shù)在index位上異或結(jié)果為1(對(duì)于異或庵朝,相同為0吗冤,不同為1)又厉,說明這兩個(gè)數(shù)在index位上是不一樣的。

使用這個(gè)判斷條件椎瘟,可以將整個(gè)數(shù)組分為兩類覆致。第一類子數(shù)組中每個(gè)數(shù)字的index位都為1,第二類子數(shù)組中每個(gè)數(shù)字的index位都為0肺蔚。這樣同時(shí)也將兩個(gè)只出現(xiàn)一次的數(shù)給分開了煌妈,而且同時(shí)保證相同的數(shù)處于同一個(gè)數(shù)組中(相同的數(shù)index位一定相同)。為了方便實(shí)現(xiàn)宣羊,我自己寫了個(gè)getFullBinaryString()函數(shù)璧诵。

得到兩個(gè)數(shù)組之后,我們就將這個(gè)問題轉(zhuǎn)化為求數(shù)組中一個(gè)數(shù)字出現(xiàn)一次的問題了仇冯。

時(shí)間復(fù)雜度為O(n)之宿,空間復(fù)雜度為O(1)


這樣說有點(diǎn)抽象苛坚,舉個(gè)例子比被,假設(shè)輸入的數(shù)組為{1,2,10,4,1,4,3,3},依次對(duì)數(shù)組中每一個(gè)數(shù)字進(jìn)行異或運(yùn)算之后泼舱,得到的二進(jìn)制結(jié)果為1000等缀。第一位為1,于是我們將index設(shè)置成1娇昙,我們根據(jù)每個(gè)數(shù)字的index位是否為1將數(shù)組分為兩部分项滑,分別得到兩個(gè)數(shù)組 和 。接下來分別對(duì)兩個(gè)數(shù)組求異或就可以得到兩個(gè)只出現(xiàn)一次的數(shù)字210了涯贞。

下面是參考代碼:

import java.math.BigInteger;
import java.util.*;

class Solution {
    public int[] singleNumbers(int[] nums) {
        // 得到兩個(gè)只出現(xiàn)一次的數(shù)字的異或結(jié)果
        int resXOR = 0;
        for (int num : nums)
            resXOR ^= num;
        String resXORString = getFullBinaryString(resXOR);

        // 計(jì)算第一個(gè)為1的位的位置枪狂,據(jù)此將原數(shù)組劃分為兩個(gè)數(shù)組
        int index = 0;
        for (int i = 1; i < 32; i++) {
            if (resXORString.charAt(i) == '1') {
                index = i;
                break;
            }
        }

        // 劃分?jǐn)?shù)組
        ArrayList<Integer> list1 = new ArrayList<>();
        ArrayList<Integer> list2 = new ArrayList<>();
        for (int num : nums) {
            String numString = getFullBinaryString(num);
            if (numString.charAt(index) == '1')
                list1.add(num);
            else list2.add(num);
        }

        return new int[] {findUnique(list1), findUnique(list2)};
    }

    public int findUnique(ArrayList<Integer> list) {
        int res = 0;
        for (int num : list) {
            res ^= num;
        }
        return res;
    }

    public String getFullBinaryString(int num) {
        String s = Integer.toBinaryString(num);
        return String.format("%032d", new BigInteger(s));
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市宋渔,隨后出現(xiàn)的幾起案子州疾,更是在濱河造成了極大的恐慌,老刑警劉巖皇拣,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件严蓖,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡氧急,警方通過查閱死者的電腦和手機(jī)颗胡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吩坝,“玉大人毒姨,你說我怎么就攤上這事《で蓿” “怎么了弧呐?”我有些...
    開封第一講書人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵闸迷,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我俘枫,道長(zhǎng)腥沽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任鸠蚪,我火速辦了婚禮今阳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘茅信。我一直安慰自己盾舌,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開白布汹押。 她就那樣靜靜地躺著,像睡著了一般起便。 火紅的嫁衣襯著肌膚如雪棚贾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,050評(píng)論 1 291
  • 那天榆综,我揣著相機(jī)與錄音妙痹,去河邊找鬼。 笑死鼻疮,一個(gè)胖子當(dāng)著我的面吹牛怯伊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播判沟,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼耿芹,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了挪哄?” 一聲冷哼從身側(cè)響起吧秕,我...
    開封第一講書人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎迹炼,沒想到半個(gè)月后砸彬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡斯入,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年砂碉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片刻两。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡增蹭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出磅摹,到底是詐尸還是另有隱情沪铭,我是刑警寧澤壮池,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站杀怠,受9級(jí)特大地震影響椰憋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜赔退,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一橙依、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧硕旗,春花似錦窗骑、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至墙基,卻和暖如春软族,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背残制。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工立砸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人初茶。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓颗祝,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親恼布。 傳聞我的和親對(duì)象是個(gè)殘疾皇子螺戳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

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