位运算是计算机科学中对二进制数进行操作的一种运算方式,主要应用于底层编程和硬件设计中。位运算符包括以下几种:
- 位非(NOT):符号为
~。对一个数的每个位取反,即0变成1,1变成0。 - 位与(AND):符号为
&。两个位都为1时,结果才为1。 - 位或(OR):符号为
|。两个位中至少有一个为1时,结果就为1。 - 位异或(XOR):符号为
^。两个位相同则结果为0,不同则结果为1。 - 位左移(Left Shift):符号为
<<。将一个数的所有位向左移动指定的位数,左边超出的位丢弃,右边空出的位补0。 - 位右移(Right Shift):符号为
>>。将一个数的所有位向右移动指定的位数,右边超出的位丢弃,左边空出的位补原数的最高位的值(对于无符号数补0,对于有符号数补最高位的值)。 - 无符号右移(Unsigned Right Shift):符号为
>>>(在某些语言中,如Java)。与右移类似,但是左边空出的位总是补0,无论原数是有符号还是无符号。
位运算的规则和特性包括:
- 位运算符通常作用于整数类型。
- 位运算符的优先级低于算术运算符,但高于比较运算符。
- 位运算符可以用于设置、清除、翻转和测试特定的位。
- 位运算符可以用于优化某些算法,比如计算最大公约数的欧几里得算法。
- 位运算符可以用于位域操作,即在底层编程中控制硬件寄存器的特定位。
位运算在编程中的应用非常广泛,特别是在需要优化性能和资源使用的情况下。
LeetCode示例:
给你一个 非空 整数数组 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),很容易想到使用 Hash 映射来进行计算,遍历一次后结束得到结果,但是在空间复杂度上会达到 O(n),需要使用较多的额外空间
既满足时间复杂度又满足空间复杂度,就要提到位运算中的异或运算 XOR,主要因为异或运算有以下几个特点:
一个数和 0 做 XOR 运算等于本身:a⊕0 = a
一个数和其本身做 XOR 运算等于 0:a⊕a = 0
XOR 运算满足交换律和结合律:a⊕b⊕a = (a⊕a)⊕b = 0⊕b = b
故而在以上的基础条件上,将所有数字按照顺序做抑或运算,最后剩下的结果即为唯一的数字
时间复杂度:O(n),空间复杂度:O(1)
答案:
class Solution {
public:
int singleNumber(vector<int>& nums) {
int ans=0;
for(int k:nums){
ans^=k;
}
return k;
}
};