文章目录
前言
本专栏文章为《LeetCode 热题 100》的刷题题解,相关内容如有侵权,立即删除。
一、题目
1、原题链接
2、题目描述
二、个人思路整理
1、思路分析
将数组中的所有元素一次进行异或运算。这样,除了目标元素(只出现一次的元素)外,其余元素均出现两次,成对出现的数字异或后会全部相互抵消为0,剩下的结果就是那个唯一只出现一次的数字。
nums 0 ⊕ nums 1 ⊕ ⋯ ⊕ nums n − 1 = ( 成对数字对消 ) ⊕ 单一数字 = 0 ⊕ 单一数字 = 单一数字 \text{nums}0 \oplus \text{nums}1 \oplus \dots \oplus \text{nums}n-1 = (\text{成对数字对消}) \oplus \text{单一数字} = 0 \oplus \text{单一数字} = \text{单一数字} nums0⊕nums1⊕⋯⊕numsn−1=(成对数字对消)⊕单一数字=0⊕单一数字=单一数字
异或运算( ⊕ \oplus ⊕)本质是模2加法(不进位加法) ,满足交换律和结合律。
异或运算的性质:
归零律: a ⊕ a = 0 a \oplus a = 0 a⊕a=0(任何数与自身异或结果为 0);
恒等律: a ⊕ 0 = a a \oplus 0 = a a⊕0=a(任何数与 0 异或结果为其本身);
交换律与结合律: a ⊕ b ⊕ c = a ⊕ c ⊕ b a \oplus b \oplus c = a \oplus c \oplus b a⊕b⊕c=a⊕c⊕b。
复杂度分析时间复杂度: O ( n ) O(n) O(n),只需遍历一次数组。
空间复杂度: O ( 1 ) O(1) O(1),仅使用一个变量存储累计异或结果。
2、解题代码
cpp
class Solution {
public:
int singleNumber(vector<int>& nums) {
int ans = 0;
for (int num : nums) {
ans ^= num;
}
return ans;
}
};
三、知识风暴
常见位运算及适用场景
| 运算/技巧 | 表达式 | 核心作用 / 适用场景 |
|---|---|---|
| 消除成对数字 | a ^ a = 0 / a ^ 0 = a |
寻找唯一出现的数字、求缺失元素。 |
| 消除最低位的 1 | n & (n - 1) |
统计二进制中 1 的个数(Brian Kernighan 算法)、快速判断是否为 2 的幂((n & (n - 1)) == 0)。 |
| 提取最低位的 1 (lowbit) | n & (-n) |
树状数组(Fenwick Tree)、将数组按某一位拆分为两组(如只出现一次的两个数字)。 |
| 判断奇偶性 | (n & 1) == 1 |
替代模运算 n % 2 != 0,判断整数奇偶。 |
| 乘/除以 2 k 2^k 2k | n << k / n >> k |
快速乘除 2 的幂次(如二分查找计算中点 (l + r) >> 1)。 |
| 交换两数 | a ^= b; b ^= a; a ^= b; |
无需临时变量交换数值(注意两变量地址不能相同)。 |
| 状态压缩 (Bitmask) | `mask | (1 << i)(置1)mask & ~(1 << i)` (清0) `(mask >> i) & 1` (查状态) |

