算法题 只出现一次的数字Ⅰ/Ⅱ/Ⅲ

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


猜你喜欢

转载自blog.csdn.net/qq_35546040/article/details/80284079