⭐算法OJ⭐位操作 Single Number 系列(C++实现)
136. Single Number
Given a non-empty array of integers nums, every element appears twice except for one. Find that single one.
You must implement a solution with a linear runtime complexity and use only constant extra space.
给定一个数组,找出 frequency 为1的数字(有唯一解),其他数字的 frequency 为2
- 先排序,再比对查找, O ( n log n ) O(n \log n) O(nlogn)
- bit 操作,XOR 的性质: A ⊕ A = 0 A\oplus A = 0 A⊕A=0, A ⊕ 0 = A A \oplus 0 = A A⊕0=A, …
class Solution {
public:
int singleNumber(vector<int>& nums) {
// A XOR A = 0, A XOR 0 = A
int res = 0;
for (int num: nums) {
res = res ^ num;
}
return res;
}
};
137. Single Number II
Given an integer array nums
where every element appears three times except for one, which appears exactly once. Find the single element and return it.
You must implement a solution with a linear runtime complexity and use only constant extra space.
class Solution {
public:
int singleNumber(vector<int>& nums) {
vector<int> bitCount(32, 0);
for (int i = 0; i < 32; i++) {
int mask = 1 << i;
for (auto num: nums) {
if (num & mask) {
bitCount[i]++;
}
}
}
int ans = 0;
for (int i = 0; i < 32; i++) {
if (bitCount[i] % 3) {
ans += 1 << i;
}
}
return ans;
}
};
位运算:
- 对于每个二进制位,统计所有数字在该位上出现的次数。
- 如果一个数字出现了三次,那么它的每个二进制位上的 1 也会出现三次。
- 只出现一次的数字的二进制位上的 1 只会出现一次。
状态机:
- 使用两个变量
ones
和twos
来记录每个二进制位的状态: ones
:表示当前位出现 1 的次数是否为 1 次。twos
:表示当前位出现 1 的次数是否为 2 次。- 当一个位出现 3 次时,重置为 0。
int singleNumber(vector<int>& nums) {
int ones = 0, twos = 0;
for (int num : nums) {
ones = (ones ^ num) & ~twos;
twos = (twos ^ num) & ~ones;
}
return ones;
}
260. Single Number III
- 首先,对整个数组进行异或运算,得到的结果是两个只出现一次的数的异或值,记为 xor。
- 然后,找到 xor 中任意一个为 1 的二进制位(这个位表示两个数在该位上不同)。
- 根据这个二进制位,将数组分为两组:
- 一组是该位为 1 的数。
- 另一组是该位为 0 的数。
- 分别对这两组进行异或运算,得到的结果就是两个只出现一次的数。
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
int axorb = 0;
for (int num: nums) {
axorb ^= num;
}
int bit = -1;
for (int i = 0; i < 32; i++) {
if (axorb & (1 << i)) {
bit = i;
break;
}
}
// bit is the rightmost digit that a differs from b
int first = 0;
for (int a: nums) {
if (a & (1 << bit)) {
first ^= a;
}
}
// identify the first unique number whose digit at *bit* digit is 1
int second = axorb ^ first;
// inverse operation
return {first, second};
}
};