1. 程式人生 > >LeetCode上的Bit Manipulation(位運算)型別的題目

LeetCode上的Bit Manipulation(位運算)型別的題目

文章目錄


Easy

461. Hamming Distance兩個數字的漢明距

461. Hamming Distance

兩個整數之間的漢明距離是相應位不同的位置數。

正常思路是以下的程式碼:
判斷兩個數字位資訊最後一位是是否不一樣,再集體右移一位。

class Solution {
    public int hammingDistance(int x, int y) {
        int res = 0;
        while(x != 0 || y != 0){
            if((x&1) != (y&1)) res++;
            x = x>>1;
            y = y>>1;
        }
        return res;
    }
}

faster than 50.77% of Java online submissions for Hamming Distance.

但是位運算有技巧就是:

  • 兩個整數相異或,得到的是兩個整數位資訊所有不同的資訊。因為異或^表示不同為1,相同為0.
  • n &= (n-1) 可以抹掉n的位資訊中最右邊的1

所以這道題於是可以這麼寫:

class Solution {
    public int hammingDistance(int x, int y) {
        int xor = x ^ y, count = 0;
        
        while (xor != 0) {
            xor &= (xor - 1);
            count++;
        }
        return count;
    }
}

faster than 60.28% of Java online submissions for Hamming Distance.


476. Number Complement 求補碼

476. Number Complement

num=101
mask=111…111000
~mask=000…000111
~num=111…111010
~num & ~mask = 010

class Solution {
    public int findComplement(int num) {
        int mask = ~0;
        while((num&mask) > 0) mask <<= 1;
        return ~num & ~mask;
    }
}

faster than 99.01% of Java online submissions for Number Complement.


136. Single Number

136. Single Number

給定一個非空的整數陣列,除了一個元素外,每個元素都會出現兩次,找到那一個。

需要知道 異或^ 的以下特點:

  • 兩個相同的數異或的結果為0
  • 0異或數字等於原數字
class Solution {
    public int singleNumber(int[] nums) {
        int res = 0;
        for(int i : nums){
            res ^= i;
        }
        return res;
    }
}

faster than 100.00% of Java online submissions for Single Number.


693. Binary Number with Alternating Bits 相互交錯的位資訊

693. Binary Number with Alternating Bits

給定正整數,檢查它的位表示是否是交替位,即兩個相鄰位總是具有不同的值。

解釋:
n = 1 0 1 0 1 0 1 0
n >> 1 = 0 1 0 1 0 1 0 1
n ^ n>>1 = 1 1 1 1 1 1 1 1
n = 1 1 1 1 1 1 1 1
n + 1 = 1 0 0 0 0 0 0 0 0
n & (n+1) = 0 0 0 0 0 0 0 0

class Solution {
    public boolean hasAlternatingBits(int n) {
        n ^= n >> 1;
        return (n&(n+1)) == 0;
    }
}

faster than 9.41% of Java online submissions for Binary Number with Alternating Bits.


389. Find the Difference

389. Find the Difference

給定兩個字串s和t,它們只包含小寫字母。 字串t由隨機混洗字串s生成,然後在隨機位置再新增一個字母。 找到t中新增的字母。

用一個256的陣列map來記錄位資訊,map[i]=a表示字元的ASCII碼為i的字元在字串中出現了a次。

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

faster than 67.92% of Java online submissions for Find the Difference.


371. Sum of Two Integers 不使用加減號進行兩個整數的相加

371. Sum of Two Integers

不使用加減號實現兩個整數的相加

  • a^b等於a和b的無進位相加
  • a&b再左移以為相當於a+b的進位
  • 一直重複直到進位消失
class Solution {
    public int getSum(int a, int b) {
        int sum = a;
	    while (b != 0) {
	    	sum = a ^ b;
	    	b = (a & b)<<1;
	    	a = sum;
	    }
	    return a;
    }
}

faster than 100.00% of Java online submissions for Sum of Two Integers.


169. Majority Element 出現次數大於一半的元素

169. Majority Element

給定大小為n的陣列,找到多數元素。多數元素是出現超過⌊n /2⌋倍的元素。 您可以假設該陣列非空,並且多數元素始終存在於陣列中。

這道題出現在Bit Manipulation的分類下面,說明可以用位運算去解,但是有更容易理解的方法:

出現次數大於一半的數只會有一個,一次在陣列刪掉兩個不同的數,不停滴刪除,直到剩下的數只有一種(不是一個),這個數就是答案。

class Solution {
    public int majorityElement(int[] nums) {
        int num = 0;
        int count = 0;
        for(int i : nums){
            if(count == 0){
                num = i;
                count++;
            }else if(num == i){
                count++;
            }else{
                count--;
            }
        }
        
        return num;
    }
}

faster than 93.88% of Java online submissions for Majority Element.


268. Missing Number 找出0到n中缺失的那個數字

268. Missing Number

給定一個包含n個不同數字的陣列,由0,1,2,…,n組成,找到陣列中缺少的數字。

利用異或的特點:

  • 兩個相同的數異或的結果為0
  • 0異或數字等於原數字
class Solution {
    public int missingNumber(int[] nums) {
        int missing = 0;
        for(int i = 1; i <= nums.length; i++){
            missing ^= i;
        }
        for(int i = 0; i < nums.length; i++){
            missing ^= nums[i];
        }
        return missing;
    }
}

faster than 69.45% of Java online submissions for Missing Number.


191. Number of 1 Bits 整數二進位制表達中有多少個1

191. Number of 1 Bits

整數二進位制表達中有多少個1?

利用位運算以下特點:

  • n &= n-1 抹掉最右邊的1
public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        int count = 0;
        while(n != 0){
            n &= n-1;
            count++;
        }
        return count;
    }
}

faster than 98.49% of Java online submissions for Number of 1 Bits.


Medium

260. Single Number III

260. Single Number III

給定一組數字nums,其中恰好兩個元素只出現一次而所有其他元素恰好出現兩次。找到只出現一次的兩個元素。

假設這兩個數是a和b,用異或的特點,數組裡面的數全部異或一遍,剩下的結果肯定是a^b。
於是用a^b的結果再在陣列中把a和b給區分出來。在 a^b 上找到一個不為0的bit位,那麼在a和b上肯定有一個這個位上位0,另外一個為1.我們用最左邊的一個1作為這個bit位。

再記住一個特點:

  • n&(~n+1) 留下n的二進位制表示的最右邊的一個1
class Solution {
    public int[] singleNumber(int[] nums) {
        int tag = 0;
        for(int i : nums){
            tag ^= i;
        }
        int[] res = new int[2];
        tag = tag&(~tag+1);
        for(int i : nums){
            if((i&tag) == 0){
                res[0] ^= i;
            }else{
                res[1] ^= i;
            }
        }
        return res;
    }
}

faster than 100.00% of Java online submissions for Single Number III.