1. 程式人生 > >演算法題 只出現一次的數字Ⅰ/Ⅱ/Ⅲ

演算法題 只出現一次的數字Ⅰ/Ⅱ/Ⅲ

136只出現一次的數字

給定一個非空整數陣列,除了某個元素只出現一次以外,其餘每個元素均出現兩次。找出那個只出現了一次的元素。

思路:本來使用HashMap做,後來才知道這是位運算方面的題,慚愧。

           由於其他元素都出現了兩次,因此把全部元素亦或一下,結果就出來了。。

class Solution {
    public static int singleNumber(int[] nums) {        
        int result=0;
        for(int i=0;i<nums.length;i++){
            result^=nums[i];
        }
        return result;
    }
}

137只出現一次的數字 II

給定一個非空整數陣列,除了某個元素只出現一次以外,其餘每個元素均出現了三次。找出那個只出現了一次的元素。

思路:其他元素都出現了三次,按位計算每一位上1的個數,結果模3為1的那些位就是所求數二進位制1所在的位。

class Solution {
    public static int singleNumber(int[] nums) {
        int result = 0;
        for(int i=0;i<32;i++){
            int mask = 1<<i;
            int count = 0;
            for(int j=0;j<nums.length;j++){
               if((mask&nums[j])!=0)
                   count++;
            }
           if(count%3==1)
               result = mask|result;
        }
        return result;
    }
}

260只出現一次的數字 III

給定一個整數陣列 nums,其中恰好有兩個元素只出現一次,其餘所有元素均出現兩次。 找出只出現一次的那兩個元素。

思路:

    原話:

這道題主要和Ⅰ類似,但是這裡有兩個不同的數,所以需要從這兩個數的異或值反推得到結果。整數的二進位制在java中是補碼錶示,所以我們可以用n&-n得到n的二進位制最右邊的一個1。這樣對於這個為1的位置,肯定可以分辨出這兩個數,因為一定有兩個數在這個位置1個為1,另一個為0。所以遍歷整個陣列,和這個數做&操作,就可以將兩個數分開到兩組中。因為其他出現兩次的數,異或操作還是為0,對結果沒有影響,所以對每個遍歷到的數做異或操作即可。

    理解:

還是先將全部數亦或一下,得到的結果n就是我們要的兩個數亦或的結果。然後反推這兩個數。n&-n(不好理解的話可以換為n & ~(n-1)理解)得到兩個數不同的最低位。接著將全部數分成兩個組,一組為該位上是0的,另一組為該位上是1的。把兩組分別組內亦或,就可以得到我們要的兩個數。

class Solution {
    public int[] singleNumber(int[] nums) {
        int sum = 0;    //記錄所有異或的值,即兩個只出現一次數的異或
        for(int i=0;i<nums.length;i++){
            sum ^= nums[i];
        }
        int[] res = new int[2];
 
        sum &= -sum;    //得出兩個數異或結果的最右邊的一個1,其他的為零,這樣進行&操作就可以將兩個不同的數分到不同的兩組去
        for(int i=0;i<nums.length;i++){
            if((sum&nums[i])==0) 
                res[0] ^= nums[i];
            else 
                res[1]^=nums[i];
        }
        return res;
    }
}
https://www.cnblogs.com/271934Liao/p/7158888.html