只出现一次的数字I II III

https://leetcode-cn.com/problems/single-number/

只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

输入: [2,2,1]
输出: 1
示例 2:

输入: [4,1,2,1,2]
输出: 4

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

https://leetcode-cn.com/problems/single-number-ii/

只出现一次的数字 II

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

输入: [2,2,3,2]
输出: 3
示例 2:

输入: [0,1,0,1,0,1,99]
输出: 99

class Solution {
    public int singleNumber(int[] nums) {
        int ans = 0;
        //考虑每一位
        for (int i = 0; i < 32; i++) {
            int count = 0;
            //考虑每一个数
            for (int j = 0; j < nums.length; j++) {
                //当前位是否是 1
                if ((nums[j] >>> i & 1) == 1) {
                    count++;
                }
            }
             //以上结果假如算出是110 的话,那么下面的结果就是得出6
            //1 的个数是否是 3 的倍数
            if (count % 3 != 0) {
                ans = ans | 1 << i;
            }
        }
        return ans;
    }
}

假如例子是 1 2 6 1 1 2 2 3 3 3, 3 个 1, 3 个 2, 3 个 3,1 个 6

1 0 0 1

2 0 1 0

6 1 1 0

1 0 0 1

1 0 0 1

2 0 1 0

2 0 1 0

3 0 1 1 

3 0 1 1

3 0 1 1     

看最右边的一列 1001100111 有 6 个 1

再往前看一列 0110011111 有 7 个 1

再往前看一列 0010000 有 1 个 1

我们只需要把是 3 的倍数的对应列写 0,不是 3 的倍数的对应列写 1   

也就是 1 1 0,也就是 6。

原因的话,其实很容易想明白。如果所有数字都出现了 3 次,那么每一列的 1 的个数就一定是 3 的倍数。之所以有的列不是 3 的倍数,就是因为只出现了 1 次的数贡献出了 1。所以所有不是 3 的倍数的列写 1,其他列写 0 ,就找到了这个出现 1 次的数。

 

 

 https://leetcode-cn.com/problems/single-number-iii/

只出现一次的数字 III

class Solution {
    public int[] singleNumber(int[] nums) {
        int[] res ={0,0};
        if(nums == null || nums.length < 1){
            return res;
        }

        int result = nums[0];
        for (int i = 1; i < nums.length; i++) {
            result = result ^ nums[i];
        }
        int indexOf1 = findFirstBit1(result);
        for (int i : nums) {
            if (isBit1(i, indexOf1)) {
                res[0] ^= i;
            } else {
                res[1] ^= i;
            }
        }
        return res;
    }
    private static boolean isBit1(int num, int indexBit) {
        num >>>= indexBit;
        return (num & 1) == 1;
    }
    private static int findFirstBit1(int num) {
        int index = 0;
        while ((num & 1) == 0 && index < 32) {
            num >>>= 1;
            index++;
        }

        return index;
    }

    private static int help(int[] nums) {
        int result = nums[0];
        for (int i = 1; i < nums.length; i++) {
            result = result ^ nums[i];
        }
        return result;
    }
}