LeetCode - 138 只出现一次的数字

题目

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

说明:

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


分析

1 本来想的是用Java里的排序,排完顺序之后,再分第一个位置 和中间位置处理, 最后返回最后一个位置

  这样的做法显然不是很好,不说用到了Java里的arrays.sort 在找出唯一的那个不是出现两次的元素用到的方法也显得很蠢。

2 后来才知道这题考的是 位运算 处理,我们知道,两个相同的数字的二进制取与操作的结果是为0,所以数组中的所有相同的元素就可以相互抵消,最后剩下的就是那个出现一次的数字,最后返回就好了

    Java 里异或操作符 不同的为1 相同的为0

    ~ 取反运算符

    & 与操作符


代码

class Solution {
    public int singleNumber(int[] nums) {
        int result = nums[0];
        for(int i = 1; i < nums.length; i++){
            result^=nums[i];
        }
        return result;
        // Arrays.sort(nums);
        // for (int i = 0; i < nums.length - 1; i++) {
        //     if(i == 0 && nums[i + 1] != nums[i]){
        //         return nums[0];
        //     }else if(i != 0 && nums[i] != nums[i - 1] && nums[i] != nums[i + 1]){
        //         return nums[i];
        //     }
        // }
        // return nums[nums.length - 1];
    }
}


扩展1

数组中其他数字都出现三次,只有一个出现一次,求出这个数

两位 表示四种状态 00 10 01 11  我们只需要三种状态 00 - 10 - 01  - 00 分别是初始状态,赋值到ones, 赋值到twos, 清空所有

ones  twos 两个bit位存储


代码

class Solution {
    public int singleNumber(int[] nums) {
        int ones = 0, twos = 0;
        for(int i = 0; i< nums.length; i++){
            ones = (ones ^ nums[i]) & ~twos;
            twos = (twos ^ nums[i]) & ~ones;
        }
        return ones;
    }
}

time: o(n)

space:o(1)


不用位运算,用hashmap 

key 存放元素的值,value存放次数

最后找出value为1的值 



拓展2

一个数组其他两次,有两个只出现了一次,求这两个数


分析

1 异或所有的数

2 diff 与上 diff的补码形式  反码加1  

    例 

    3 011 

    5 101

    3&5 = 110 = diff = 6

    -diff = 1111010

    与上结果为 10

    结论 a b不相同,那么ab的二进制有且只有一位是不相同的

    6 & -6 10

    那么得知 不同的一位是倒数第二位

    就将原数组分为两个 一个是第二位为1  一个为0 分别对这两个数组取异或运算,就能得到最终结果


代码    

public int[] singleNumber(int[] nums) {
        int diff = 0;
        for (int i = 0; i < nums.length; i++) {
            diff ^= nums[i];
        }
        diff &= -diff;
        int res[] = new int[2];
        for (int i = 0; i < nums.length; i++) {
            if((nums[i] & diff) == 0){
                res[0] ^= nums[i];
            }else{
                res[1] ^= nums[i];
            }
        }
        return res;  
    }

你可能感兴趣的:(LeetCode)