LeetCode中位運算相關(guān)算法匯總!A薇簟轨奄!

前提知識:

  • <<表示左移移,不分正負數(shù)拒炎,低位補0挪拟;
  • >>表示右移,如果該數(shù)為正击你,則高位補0玉组,若為負數(shù),則高位補1丁侄;
  • >>>表示無符號右移惯雳,也叫邏輯右移,即若該數(shù)為正鸿摇,則高位補0石景,而若該數(shù)為負數(shù),則右移后高位同樣補0

異或運算性質(zhì):

  • 任何數(shù)和 0 做異或運算户辱,結(jié)果仍然是原來的數(shù)鸵钝,即 a ⊕ 0 = a。
  • 任何數(shù)和其自身做異或運算庐镐,結(jié)果是 0恩商,即 a ⊕ a = 0
  • 異或運算滿足交換律和結(jié)合律,即 a⊕b⊕a=b⊕a⊕a=b⊕(a⊕a)=b⊕0=b必逆。

231. 2 的冪

題解1:首先想到的是判斷這個數(shù)是否為偶數(shù)怠堪,如果是偶數(shù)揽乱,就一直除以2 , 直到是奇數(shù)為止粟矿, 最后在判斷這個奇數(shù)是否等于1凰棉,但是會發(fā)現(xiàn)超過時間限制,所以我們換一種思路陌粹, 其實n 就只能是1 撒犀,2 , 4 掏秩, 8 或舞, 1 6 … … 這樣的數(shù)字,他們都有一個特點蒙幻,二進制位中只有一個1映凳,也就是說滿足這個條件,那么這個數(shù)肯定是2 的冪次方邮破。

class Solution {
    public boolean isPowerOfTwo(int n) {
        if (n <= 0){
            return false;
        }
        int count = 0;
        for (int i = 0; i < 32; i++) {

            if (((n >>> i) & 1) == 1){
                count++;
            }
        }
        return count == 1;
    }
}

題解2:劍指 Offer 15. 二進制中1的個數(shù)中通過(n & (n-1))可以消去二進制位中最右邊的1诈豌,如果n 的二進制位中只有一個1 , 那么n & ( n - 1 ) 的結(jié)果肯定是0 抒和, 所以我們只需要判斷n 大于0 的時候矫渔, n & ( n - 1 ) 是否等于0 即可, 一行代碼搞定构诚。

class Solution {
    public boolean isPowerOfTwo(int n) {
        if (n <= 0){
            return false;
        }
        return (n & (n-1)) == 0;
    }
}

題解3:n 和- n 在二進制位中的區(qū)別蚌斩, 因為- n 是n 每一個都取反然后再加上1 的結(jié)果, 所以n 和- n 的區(qū)別就是n 原來右邊第一個1 以及他右邊的都不變范嘱,所以在確定n大于0的情況下送膳,只需要判斷(n&-n)==n即可,也是一行代碼搞定丑蛤。

class Solution {
    public boolean isPowerOfTwo(int n) {
        return n > 0 && (n & -n) == n;
    }
}

劍指 Offer 15. 二進制中1的個數(shù)

題解:18種解法叠聋,這個帖子講了18種解法。列出常用的兩種:

題解1:把n往右移32次受裹,每次都和1進行與運算

public int hammingWeight(int n) {
    int count = 0;
    for (int i = 0; i < 32; i++) {
        if (((n >>> i) & 1) == 1) {
            count++;
        }
    }
    return count;
}

題解2:這個是最常見的碌补,每次消去最右邊的1,直到消完為止

public int hammingWeight(int n) {
    int count = 0;
    while (n != 0) {
        n &= n - 1;
        count++;
    }
    return count;
}

136. 只出現(xiàn)一次的數(shù)字

異或運算性質(zhì):

  • 任何數(shù)和 0 做異或運算棉饶,結(jié)果仍然是原來的數(shù)厦章,即 a ⊕ 0 = a。
  • 任何數(shù)和其自身做異或運算照藻,結(jié)果是 0袜啃,即 a ⊕ a = 0
  • 異或運算滿足交換律和結(jié)合律,即 a⊕b⊕a=b⊕a⊕a=b⊕(a⊕a)=b⊕0=b幸缕。
class Solution {
    public int singleNumber(int[] nums) {
        int res = 0;
        for (int num : nums) {
            res ^= num;
        }
        return res;
    }
}

260. 只出現(xiàn)一次的數(shù)字 III

該題滑動窗口專題有講解群发,本專題位運算解法晰韵。

位運算,異或運算有性質(zhì)如下:

  • 任何數(shù)和 0 做異或運算熟妓,結(jié)果仍然是原來的數(shù)雪猪,即 a ⊕ 0 = a。
  • 任何數(shù)和其自身做異或運算起愈,結(jié)果是 0只恨,即 a ⊕ a = 0
  • 異或運算滿足交換律和結(jié)合律,即 a⊕b⊕a=b⊕a⊕a=b⊕(a⊕a)=b⊕0=b告材。

題解:基于位運算性質(zhì)

  1. 先將數(shù)組的所有元素異或得到的一個結(jié)果坤次,這個結(jié)果為不存在重復的兩個元素異或的結(jié)果,因為相同的都已經(jīng)抵消掉了斥赋,同時也不為0,因為這兩個元素是不同的产艾。
  2. 然后我們需要將來數(shù)組分為兩組疤剑,一組包含其中一個我們需要的結(jié)果,另外一組包含另外一個我們需要的結(jié)果闷堡,同時相同的元素必須分到一組隘膘,這樣,我們對每一組的所有元素分別進行異或杠览,就可以在每一組中得到一個我們想要的結(jié)果弯菊,怎么做呢?
  3. lab &= ?lab得到出 lab最右側(cè)的1,因為異或值為1踱阿,說明我們需要的兩個值里面其中一個為0管钳,另外一個為1,這樣才能異或為1
  4. 然后遍歷软舌,分組才漆,每一組分別異或就可以了
class Solution {
    public int[] singleNumber(int[] nums) {
        int[] res = new int[2];
        int lab = 0;
        for(int num : nums){
            lab ^= num;
        }
        lab &= -lab;
        for(int num : nums){
            if ((num & lab) != 0){
                res[0] ^= num;
            }else {
                res[1] ^= num;
            }
        }
        return res;
    }
}

劍指 Offer II 004. 只出現(xiàn)一次的數(shù)字

137. 只出現(xiàn)一次的數(shù)字 II

題解:在java中int類型是32位,我們需要統(tǒng)計所有數(shù)字在某一位置的和能不能被3整除佛点,如果不能被3整除醇滥,說明那個只出現(xiàn)一次的數(shù)字的二進制在那個位置是1……把32位全部統(tǒng)計完為止。

class Solution {
    public int singleNumber(int[] nums) {
        int res = 0;
        for (int i = 0; i < 32; i++) {

            int oneCount = 0;
            for (int j = 0; j < nums.length; j++) {
                oneCount += (nums[j] >>> i) & 1;
            }
            if (oneCount % 3 != 0){
                res |= 1 << i;//按位或超营,給相應(yīng)的位置賦1
            }
        }
        return res;
    }
}

位運算部分小結(jié)

類似的題:136. 只出現(xiàn)一次的數(shù)字鸳玩、260. 只出現(xiàn)一次的數(shù)字 III劍指 Offer II 004. 只出現(xiàn)一次的數(shù)字

一演闭,如果只有一個數(shù)字出現(xiàn)一次不跟,其他數(shù)字都出現(xiàn)偶數(shù)次,我們只需要把所有數(shù)字異或一遍即可船响。例如:136題目Leetcode連接

因為異或有下面幾條性質(zhì)

  • a^a=0 任何數(shù)字和自己異或結(jié)果是0
  • a^0=a 任何數(shù)字和0異或還是他自己
  • abc=acb 異或運算具有交換律

二躬拢,如果只有一個數(shù)字出現(xiàn)一次躲履,其他數(shù)字都出現(xiàn)奇數(shù)次,我們可以用下面代碼來解決聊闯。例如:劍指 Offer II 004. 只出現(xiàn)一次的數(shù)字

class Solution {
    public int singleNumber(int[] nums,int n) {
        int res = 0;
        for (int i = 0; i < 32; i++) {
            int oneCount = 0;
            for (int j = 0; j < nums.length; j++) {
                oneCount += (nums[j] >>> i) & 1;
            }
            if (oneCount % n != 0){
                res |= 1 << i;//按位或工猜,給相應(yīng)的位置賦1
            }
        }
        return res;
    }
}

劍指 Offer 53 - II. 0~n-1中缺失的數(shù)字

題解:把所有數(shù)字都跟自己對應(yīng)的下標異或,最后將結(jié)果與長度異或就可以得到結(jié)果菱蔬,因為如果是正常順序的話篷帅,所有數(shù)字都跟自己對應(yīng)的下標相等,異或后結(jié)果為0拴泌,最后與長度異或就可以得到最終的結(jié)果魏身,以[0,1,2,3,4,5,6,7,9]為例,異或到最后一個數(shù)字時res=98,然后異或長度9蚪腐,即res=98^9=8箭昵。

異或性質(zhì):

  • a^a=0 任何數(shù)字和自己異或結(jié)果是0
  • a^0=a 任何數(shù)字和0異或還是他自己
  • abc=acb 異或運算具有交換律
class Solution {
    public int missingNumber(int[] nums) {
        int res = 0;
        for (int i = 0; i < nums.length; i++) {
            res ^= nums[i] ^ i;
        }
        return res ^ nums.length;
    }
}

389. 找不同

題解一:136. 只出現(xiàn)一次的數(shù)字幾乎一模一樣的題目。

class Solution {
    public char findTheDifference(String s, String t) {
        char res = 0;
        String str = s + t;
        for (int i = 0; i < str.length(); i++) {
            res ^= str.charAt(i);
        }
        return res;
    }
}

題解二:既然字符串s 比t 少一個字符回季, 我們先統(tǒng)計字符串s 中每個字符的數(shù)量家制, 然后減去字符串t中的每個字符, 如果小于0 泡一, 說明字符串s 比t 少的就是這個字符颤殴, 直接返回即可。

class Solution {
    public char findTheDifference(String s, String t) {
        int[] count = new int[26];
        for(int i = 0; i < s.length();i++){
            count[s.charAt(i) - 'a']++;
        }
        for(int i = 0; i < t.length(); i++){
            int val = --count[t.charAt(i) - 'a'];
            if(val < 0){
                return t.charAt(i);
            }
        }
        return 'a';
    }
}

題解三:用t 中所有字符的和減去s 中所有字符的和鼻忠, 最后結(jié)果就是要求的那個字符涵但。

class Solution {
    public char findTheDifference(String s, String t) {
        char res = 0;
        for(int i = 0; i < t.length();i++){
            res += t.charAt(i);
        }
        for(int i = 0; i < s.length(); i++){
            res -= s.charAt(i);
        }
        return res;
    }
}

1442. 形成兩個異或相等數(shù)組的三元組數(shù)目

題解:a 的值是數(shù)組[ i … … j - 1 ] 中所有元素的異或結(jié)果, b 的值是數(shù)組[ j … … k ] 中所有元素的異或結(jié)果帖蔓, 并且a 中異或的元素和b 中異或的元素是連續(xù)的并且沒有重疊矮瘟。如果要讓a = = b,那么就是a ^ b = 0 讨阻, 也就是arr[i]^arr[i+1]^……^arr[j]^……^arr[k]=0;所以問題就轉(zhuǎn)化成了從數(shù)組a r r 中找到一些連續(xù)的元素芥永, 他們的異或結(jié)果等于0 即可

i<j钝吮,并且j可以等于k埋涧,這個k我們不需要管,所以至少需要2個元素奇瘦。也就是說從數(shù)組arr中找到至少2個以上的連續(xù)的元素他們的異或結(jié)果是0即可成立三元組(i,j,k)棘催。另外連續(xù)n 個元素的異或結(jié)果是0 , 那么可能的組合就有n - 1 種耳标。這樣就很容易解這道題了醇坝。

class Solution {
    public int countTriplets(int[] arr) {
        int ret = 0;
        for (int i = 0; i < arr.length; i++) {
            int res = arr[i];
            for (int j = i+1; j < arr.length; j++) {
                res ^= arr[j];
                if (res == 0){
                    ret += (j-i);
                }
            }
        }
        return ret;
    }
}

461. 漢明距離

題解:先異或,然后求異或后結(jié)果中1的個數(shù)就行。

class Solution {
    public int hammingDistance(int x, int y) {
        int res = 0;
        int num = x ^ y;
        for (int i = 0; i < 32; i++) {
            if (((num >>> i) & 1) == 1){
                res++;
            }
        }
        return res;
    }
}

1356. 根據(jù)數(shù)字二進制下 1 的數(shù)目排序

題解:從題中可以看到0<=arr[i]<=10^4呼猪,所以我們可以將原來數(shù)中1的個數(shù)乘100000 + 原來的數(shù)值画畅,然后再排序,排序完后在逐個還原宋距。

class Solution {
    public int[] sortByBits(int[] arr) {

        for (int i = 0; i < arr.length; i++) {
            arr[i] = Integer.bitCount(arr[i]) * 100000 + arr[i];
        }
        Arrays.sort(arr);
        for (int i = 0; i < arr.length; i++) {
            arr[i] = arr[i] % 100000;
        }
        return arr;
    }
}

693. 交替位二進制數(shù)

題解:一個數(shù)的二進制位如果是0和1交替轴踱,那么把這個數(shù)往右移一位然后再和原來的數(shù)進行異或運算,就會讓他全部變?yōu)?谚赎,然后加上1淫僻,那么原來的位置就都變成了0,再跟原來的數(shù)異或壶唤,判斷是否為0即可雳灵。

class Solution {
    public boolean hasAlternatingBits(int n) {
        n ^= (n >>> 1);
        return (n & (n + 1)) == 0;
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市闸盔,隨后出現(xiàn)的幾起案子悯辙,更是在濱河造成了極大的恐慌,老刑警劉巖迎吵,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笑撞,死亡現(xiàn)場離奇詭異,居然都是意外死亡钓觉,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門坚踩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荡灾,“玉大人,你說我怎么就攤上這事瞬铸∨希” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵嗓节,是天一觀的道長荧缘。 經(jīng)常有香客問我,道長拦宣,這世上最難降的妖魔是什么截粗? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮鸵隧,結(jié)果婚禮上绸罗,老公的妹妹穿的比我還像新娘。我一直安慰自己豆瘫,他們只是感情好珊蟀,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著外驱,像睡著了一般育灸。 火紅的嫁衣襯著肌膚如雪腻窒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天磅崭,我揣著相機與錄音儿子,去河邊找鬼。 笑死绽诚,一個胖子當著我的面吹牛典徊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播恩够,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼卒落,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蜂桶?” 一聲冷哼從身側(cè)響起儡毕,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎扑媚,沒想到半個月后腰湾,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡疆股,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年费坊,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片旬痹。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡附井,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出两残,到底是詐尸還是另有隱情永毅,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布人弓,位于F島的核電站沼死,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏崔赌。R本人自食惡果不足惜意蛀,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望峰鄙。 院中可真熱鬧浸间,春花似錦、人聲如沸吟榴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至兜看,卻和暖如春锥咸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背细移。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工搏予, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人弧轧。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓雪侥,卻偏偏與公主長得像,于是被迫代替她去往敵國和親精绎。 傳聞我的和親對象是個殘疾皇子速缨,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

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