Bootstrap

LeetCode热题100(136.只出现一次数字)

一.只出现一次数字

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

你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。

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

示例 2 :
输入:nums = [4,1,2,1,2]
输出:4

示例 3 :
输入:nums = [1]
输出:1

提示:
1 <= nums.length <= 3 * 104
-3 * 104 <= nums[i] <= 3 * 104
除了某个元素只出现一次以外,其余每个元素均出现两次。

解题思路:

其实这道题可以有多种解法.
我们可以暴力遍历,统计所有数字出现的次数,最后回过头来再遍历找到只出现一次那个数字.
但是这种方法性能太低,时间复杂度为O(n),并且我们需要建立数组或者Map集合来统计次数,不符合题目的限制.

我们注意到这道题,其他数字出现都是两次,所以我们应该换一种思路.
大家应该都了解位运算中的异或运算,我们来仔细研究一下他的特性.
我们先来复习一下什么是异或运算.
例如:
数字 8 转化为二进制为 0000 1000
数字 10 转化为二进制为 0000 1010
异或运算就是对位不同置为1,对位相同置为0.
例如8^10的结果就是 0000 0010,转化为10机制就是2.
还有一种特性,0对任意数字异或都等于这个数字.
那我们借助这种运算特性,如果数字相同的异或,那会有什么结果呢?
是不是结果会是0,因为数字相同代表每一位都相同,所以异或以后就是0.
回过头再来看这个题,我们不就可以利用这个特性完成这个题目结果了吗,相同的都为0,数组中所有的数字进行异或运算那么余下来的最后那一个就是我们找到只出现一次的数字 .

代码如下

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