【算法】【线性表】【数组】只出现一次的数字

发布时间 2024-01-07 21:48:01作者: 酷酷-

1  题目

给你一个 非空 整数数组 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
  • 除了某个元素只出现一次以外,其余每个元素均出现两次。

2  解答

class Solution {
    public int singleNumber(int[] nums) {
        int res = 0;
        for (int num : nums) {
            // 这玩意你不知道异或的用法,咋做呢,是不是
            res ^= num;
        }
        return res;
    }
}

3  异或探究

凭借异或的两个特性,如果数组是这样[1,1,2,2,3,3,5]的话很好理解:0 ^ 1 = 1,1 ^ 1 = 0,0 ^ 2 = 2,2 ^ 2 = 0……。而程序中为什么可以忽略数组变量的排列顺序得到想要的结果呢?
通过两个例子来看:
[1,3,1,3]异或:

 [1,2,3,4]异或:

可以看出,因为异或是按位运算,多个数异或其实就是根据这一位上1的奇偶判断:
1、偶数个1(包括0),该位为0;
2、奇数个1,该位为1。
由此,带入上面的题目就很好理解了,除开单独的数,其他数异或运算时每一位上1的个数一定是偶数个

这么想把一个个数排列起来,偶数出现的数每一列上都是的1都是偶数,都会变为0,就剩那个奇数的数了。

简单的可以理解为异或的运算顺序与“+”类似,可以随意的调换运算顺序而不影响结果。

4  异或交换

同样的,使用异或交换值的过程就很好理解了:

a = a ^ b;
b = a ^ b;
a = a ^ b;

第二步b = a ^ b转换为b = a ^ b ^ b = a;
第三步a = a ^ b转换为a = a ^ b ^ a = b;

加油。