题目速览
在一个班级中,每位同学都拿到了一张卡片,上面有一个整数。有趣的是,除了一个数字之外,所有的数字都恰好出现了两次。
现在需要你帮助班长小C快速找到那个拿了独特数字卡片的同学手上的数字是什么。
要求:
1.设计一个算法,使其时间复杂度为 O(n),其中 n是班级的人数。
2.尽量减少额外空间的使用,以体现你的算法优化能力。
解题思路
我们只需要进行一次循环,找到只出现一次的数即可。
假设,其余的数出现次数均大于一,只有一个数出现一次。这时我们只需要额外定义一个数组就可解决问题。
但题目希望尽量少使用额外空间,那应该怎么办呢?接下来介绍的位运算可以很好的解决问题。
位运算
基本运算符
| 符号 | 描述 | 运算规则 | 应用场景 |
|---|---|---|---|
| & | 与 | 两个位都为1时,结果才为1。 | 常用于取数的某些特定位,如掩码操作,可通过与一个合适的掩码值进行按位与运算来提取或清除特定的位。 |
| | | 或 | 两个位都为0时,结果才为0。 | 常用于设置某些位的值,比如将某个数的特定位设为 1。 |
| ^ | 异或 | 两个位相同为0,相异为1。 | 可用于在不使用临时变量的情况下交换两个数的值,也用于数据加密等领域中的简单加密算法,因为对同一个数进行两次相同的异或操作可以还原。 |
| ~ | 取反 | 0变1,1变0。 | |
| << | 左移 | 二进制位全部左移若干位,高位丢弃,低位补0。 | 左移一位相当于乘以 2,左移 n 位相当于乘以 2 的 n 次方。可用于快速的乘法运算(对于 2 的幂次乘法)。 |
| >> | 右移 | 二进制位全部右移若干位,对无符号数,高位补0,有符号数,右移补1。 | 右移一位相当于除以 2(对于无符号数或正数的算术右移情况),右移 n 位相当于除以 2 的 n 次方。 |
常用运算操作
- 将
x最右边的n位清零:x & (~0 << n) - 获取
x的第n位值(0或者1):(x >> n) & 1 - 获取
x的第n位的幂值:x & (1 << (n -1)) - 仅将第
n位置为1:x | (1 << n) - 仅将第
n位置为0:x & (~ (1 << n)) - 将
x最高位至第n位(含)清零:x & ((1 << n) - 1) - 将第
n位至第0位(含)清零:x & (~ ((1 << (n + 1)) - 1))
解题方案
题目让我们找出唯一出现的数,我们使用异或运算,相同的数字异或结果为0,从而得到唯一的不同数字。 异或运算原理如下:
- 任何数和 0 做异或运算,结果仍然是原来的数,即 a⊕0=a。
- 任何数和其自身做异或运算,结果是 0,即 a⊕a=0。
- 异或运算满足交换律和结合律,即 a⊕b⊕a=b⊕a⊕a=b⊕(a⊕a)=b⊕0=b 因此,本题解决。
总结
位运算是一种基于二进制的计算,运算速度很快,合理使用可以更好地解决问题。
推荐阅读
位运算全面总结,关于位运算看这篇就够了-CSDN博客
LeetCode从入门到超凡(五)深入浅出---位运算-CSDN博客