📝 题目描述

题目链接只出现一次的数字

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

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

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
示例 1 :

输入:nums = [2,2,1]

输出:1

示例 2 :

输入:nums = [4,1,2,1,2]

输出:4

示例 3 :

输入:nums = [1]

输出:1

提示:

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

💡 解题思路

方法一:位运算

使用位运算。对于这道题,可使用异或运算 。异或运算有以下三个性质。

  • 任何数和 00 做异或运算,结果仍然是原来的数,即 a0=aa⊕0=a
  • 任何数和其自身做异或运算,结果是 00,即 aa=0a⊕a=0
  • 异或运算满足交换律和结合律,即 aba=baa=b(aa)=b0=ba⊕b⊕a=b⊕a⊕a=b⊕(a⊕a)=b⊕0=b

假设数组中有 2m+12m+1 个数,其中有 mm 个数各出现两次,一个数出现一次。令 a1​、a2​、ama_1​、a_2​、…、a_m​ 为出现两次的 mm 个数,bb​ 为出现一次的数。根据性质3,数组中的全部元素的异或运算结果总是可以写成如下形式:

(a1a1)(a2a2)(amam)b(a_1​⊕a_1​)⊕(a_2​⊕a_2​)⊕⋯⊕(a_m​⊕a_m​)⊕b​

根据性质2和性质1,上式可化简和计算得到如下结果:

000b=b0⊕0⊕⋯⊕0⊕b=b

因此,数组中的全部元素的异或运算结果即为数组中只出现一次的数字。

🔧 代码实现

1、位运算

1
2
3
4
5
6
7
8
9
10
class Solution {
public:
int singleNumber(vector<int>& nums) {
int res = 0;
for (auto e : nums) {
res ^= e;
}
return res;
}
};

📊 复杂度分析

1、位运算

  • 时间复杂度O(n)O(n),其中 nn 是数组长度,只需要对数组遍历一次。
  • 空间复杂度O(1)O(1),无需使用额外空间。

🎯 总结

  • 核心思想:技巧类题目,记住即可。