[Leedcode][JAVA][面試題56 - I][第260題][位運算][HashSet]

【問題描述】 [面試題56 - I] [數(shù)組中數(shù)字出現(xiàn)的次數(shù)]

一個整型數(shù)組 nums 里除兩個數(shù)字之外什湘,其他數(shù)字都出現(xiàn)了兩次长赞。請寫程序找出這兩個只出現(xiàn)一次的數(shù)字。要求時間復雜度是O(n)闽撤,空間復雜度是O(1)得哆。

 

示例 1:

輸入:nums = [4,1,4,6]
輸出:[1,6] 或 [6,1]


【解答思路】

1.位運算

【1,4哟旗,4贩据,6】

  • 根據(jù)異或的性質(zhì)栋操,相同異或結(jié)果為 0,相異的異或結(jié)果為 1饱亮,所以將數(shù)組中的數(shù)字做異或運算矾芙,得到兩個只出現(xiàn)一次數(shù)字的異或結(jié)果。
    1 ^ 4 ^ 4 ^ 6 = 7


    image.png
  • 由于兩數(shù)字不同近上,異或結(jié)果不為 0剔宪,則其二進制中必然有一位是不相同的。
    方法一: 7 & i = 0 (出現(xiàn)0 證明可以作為分組依據(jù) )



    方法二:7 & -7 = 0001


    image.png
  • 可以先找到不相同的位壹无,就可以將數(shù)組分成兩組葱绒,再像之前那樣做異或運算。


    根據(jù)最后一位分組
class Solution {
    // 自己尋找最右邊 1 的位置
    public int[] singleNumbers(int[] nums) {
        if (nums == null || nums.length < 2) return new int[0];
        int xor = 0; // 數(shù)組第一次異或的結(jié)果斗锭,即兩個只出現(xiàn)一次的數(shù)的異或結(jié)果
        for (int num : nums) xor ^= num;
        // 尋找右邊第一個 1哈街,也就是最右邊不相同的位
        int i = 1;
        while ((i & xor) == 0){
            i <<= 1;
        }
        int[] res = new int[2];
        for (int num : nums) {
            if ((i & num) == 0) res[0] ^= num;
            else res[1] ^= num;
        }
        return res;
    }


    // 位運算 xor & (-xor)
    public int[] singleNumbers(int[] nums) {
        if (nums == null || nums.length < 2) return new int[0];
        int xor = 0; // 表示兩個只出現(xiàn)一次的數(shù)字的異或結(jié)果
        for (int num : nums) xor ^= num;

        xor &= -xor;
        int[] res = new int[2];
        for (int num : nums) {
            if ((xor & num) == 0) res[0] ^= num;
            else res[1] ^= num;
        }
        return res;
    }
}


2. HashSet

遍歷數(shù)組,遇到的數(shù)如果 HashSet 中存在拒迅,就把這個數(shù)刪除骚秦。如果不存在,就把它加入到 HashSet 中璧微。最后 HashSet 中剩下的兩個數(shù)就是我們要找的了作箍。

時間復雜度:O(N) 空間復雜度:O(N)

public int[] singleNumber(int[] nums) {
    HashSet<Integer> set = new HashSet<>();
    for (int n : nums) {
        if (set.contains(n)) {
            set.remove(n);
        } else {
            set.add(n);
        }
    }
    int[] result = new int[2];
    int i = 0;
    for (int n : set) {
        result[i] = n;
        i++;
    }
    return result;
}

【總結(jié)】

1. 位運算
異或運算(^)
運算規(guī)則:0^0=0;  0^1=1前硫;  1^0=1胞得;   1^1=0;
即:參加運算的兩個對象屹电,如果兩個相應位為“異”(值不同)阶剑,則該位結(jié)果為1,否則為0危号。
5 ^ 1  = 0101 ^ 0001 = 0100 = 4
5 ^ 3  = 0101 ^ 0011 = 0110 = 6
用法
1. 翻轉(zhuǎn)指定位 對應位異或1
X=10101110牧愁,使X低4位翻轉(zhuǎn),用X ^0000 1111 = 1010 0001即可得到外莲。
2.兩個數(shù)是否相等 ==0
 5 ^ 5  = 0101 ^ 0101 = 0000 = 0

與運算(&)
運算規(guī)則:0&0=0;  0&1=0;   1&0=0;    1&1=1;
即:兩位同時為“1”猪半,結(jié)果才為“1”,否則為0
5 & 1 = 0101 & 0001 = 0001 = 1
5 & 2 = 0101 & 0010 = 0000 = 0
用法 
取指定位   對應位與1
設(shè)X=10101110偷线,
取X的低4位磨确,用 X & 0000 1111 = 00001110 即可得到;

或運算(|)
運算規(guī)則:0|0=0声邦;  0|1=1乏奥;  1|0=1;   1|1=1亥曹;
即 :參加運算的兩個對象只要有一個為1邓了,其值為1
用法:
指定位置置1  對應位或1
將X=10100000的低4位置1 盏檐,用X | 0000 1111 = 1010 1111即可得到

取反運算(~)
運算規(guī)則:~1=0;  ~0=1驶悟;
即:對一個二進制數(shù)按位取反胡野,即將0變1,1變0

帶符號左移運算(<<)
若左移時舍棄的高位不包含1痕鳍,則每左移一位硫豆,相當于該數(shù)乘以2(右邊補0)
3 << 1 = 0011 <<1 = 0110 = 6
帶符號右移運算(>>)
正數(shù)操作數(shù)每右移一位,相當于該數(shù)除以2
(左補0 or 補1得看被移數(shù)是正還是負)
5 >> 1 = 0101 >> 1 = 0010 = 2
5 >> 2 = 0101 >> 2 = 0001 = 1
 -14 >> 2 = 11110010 >> 2 = 11111100 = -4
無符號右移運算(>>>) 
5 >>> 1 = 0101 >>> 1 = 0010 = 2
 -14 >>>2 =11111111 11111111 1111111111110010  >>>2 = 00111111 11111111 1111111111111100 =  1073741820
移位總結(jié)
- 正數(shù)的左移與右移笼呆,負數(shù)的無符號右移熊响,就是相應的補碼移位所得,在高位補0即可诗赌。
- 負數(shù)的右移汗茄,就是補碼高位補1,然后按位取反加1即可。
2. 位運算 判相等異或^ 取位與&1 置位或|1
3. HashMap 或 HashSet常見用法

** 3.1 ** HashSet
(1)增加
public boolean add(E e);
(2)刪除
public boolean remove(Object j);
(3)對比查找
public boolean contains(Object j);
(4)清空集合
public void clear();
(5)獲取長度
public int size();
** 3.2 **HashMap
(1) 插入鍵值對數(shù)據(jù)
public V put(K key, V value)
(2)根據(jù)鍵值獲取鍵值對值數(shù)據(jù)
public V get(Object key)
(3)獲取Map中鍵值對的個數(shù)
public int size()
(4)判斷Map集合中是否包含鍵為key的鍵值對
public boolean containsKey(Object key)
(5)判斷Map集合中是否包含值為value的鍵值對
boolean containsValue(Object value)
(6)判斷Map集合中是否沒有任何鍵值對
public boolean isEmpty()
(7)清空Map集合中所有的鍵值對
public void clear()
(8)根據(jù)鍵值刪除Map中鍵值對
public V remove(Object key)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末铭若,一起剝皮案震驚了整個濱河市洪碳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌叼屠,老刑警劉巖瞳腌,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異镜雨,居然都是意外死亡嫂侍,警方通過查閱死者的電腦和手機荚坞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門挑宠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人颓影,你說我怎么就攤上這事各淀。” “怎么了瞭空?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵揪阿,是天一觀的道長疗我。 經(jīng)常有香客問我咆畏,道長,這世上最難降的妖魔是什么吴裤? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任旧找,我火速辦了婚禮,結(jié)果婚禮上麦牺,老公的妹妹穿的比我還像新娘钮蛛。我一直安慰自己鞭缭,他們只是感情好,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布魏颓。 她就那樣靜靜地躺著岭辣,像睡著了一般。 火紅的嫁衣襯著肌膚如雪甸饱。 梳的紋絲不亂的頭發(fā)上沦童,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音叹话,去河邊找鬼偷遗。 笑死,一個胖子當著我的面吹牛驼壶,可吹牛的內(nèi)容都是我干的氏豌。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼热凹,長吁一口氣:“原來是場噩夢啊……” “哼泵喘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起般妙,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤涣旨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后股冗,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霹陡,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年止状,在試婚紗的時候發(fā)現(xiàn)自己被綠了烹棉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡怯疤,死狀恐怖浆洗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情集峦,我是刑警寧澤伏社,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站塔淤,受9級特大地震影響摘昌,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜高蜂,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一聪黎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧备恤,春花似錦稿饰、人聲如沸锦秒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽旅择。三九已至,卻和暖如春侣姆,著一層夾襖步出監(jiān)牢的瞬間砌左,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工铺敌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留汇歹,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓偿凭,卻偏偏與公主長得像产弹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子弯囊,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

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

  • 本系列出于AWeiLoveAndroid的分享痰哨,在此感謝,再結(jié)合自身經(jīng)驗查漏補缺匾嘱,完善答案斤斧。以成系統(tǒng)。 Java基...
    濟公大將閱讀 1,528評論 1 6
  • 面向?qū)ο笾饕槍γ嫦蜻^程霎烙。 面向過程的基本單元是函數(shù)撬讽。 什么是對象:EVERYTHING IS OBJECT(萬物...
    sinpi閱讀 1,054評論 0 4
  • 1.import static是Java 5增加的功能,就是將Import類中的靜態(tài)方法,可以作為本類的靜態(tài)方法來...
    XLsn0w閱讀 1,222評論 0 2
  • 接口/抽象類意義規(guī)范悬垃、擴展游昼、回調(diào)為其子類提供一個公共的類型 封裝子類中得重復內(nèi)容 定義抽象方法,子類雖然有不同的實...
    MigrationUK閱讀 2,165評論 1 28
  • 一:java概述:1尝蠕,JDK:Java Development Kit烘豌,java的開發(fā)和運行環(huán)境,java的開發(fā)工...
    ZaneInTheSun閱讀 2,650評論 0 11