260. 只出现一次的数字 III
思路
(位运算)
前置知识:
相同数异或为 0 ,比如 a ^ a = 0 。
假设这两个只出现一次的数字分别为 x 和 y ,根据上述性质,我们将 nums 数组中的所有数都异或一
遍,可以得到 x ^ y 。两个不同的数,其二进制表示中必然有一位是不同的,因此我们在 x ^ y 随便找
到一个不同点,假设找到了为 1 的第 k 位。
我们可以根据第 k 位的不同,将序列分为两个集合,第 k 位为 1 的集合和第 k 位不是 1 的集合,其中
x , y 分别在这两个集合,且相同的元素是在同一个集合里面,于是将其转化成了求重复数字中的单个
数值的问题。
我们将第 k 位为 1 的集合的所有数异或一遍,相同数相消,剩下的就是只出现一次的数,另一个数则为
x ^ y 再异或刚才我们求出的数。
时间复杂度分析: 。
c++代码
vector<int> res;
int start = 0, end = 0;
for(int i = 0; i < s.size(); i++){
end = max(end, hash[s[i]]);
if(i == end){
res.push_back(end - start + 1);
start = end = i + 1;
}
}
return res;
}
};
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public:
// 相同数异或为0,a ^ a = 0
/**
异或得到 sum = x^y
取 x与y中第k位为1的数
将数分为两个集合,第k位为1的集合和第k位不是1的集合
其中x y分别在这两个集合,且相同的元素是在同一个集合里面
于是将其转化成了求重复数字中的单个数值的问题
**/
vector<int> singleNumbers(vector<int>& nums) {
int sum = 0;
for(int x : nums) sum ^= x; // sum = first ^ second;
int k = 0;
while(!(sum >> k & 1)) k++; //找到sum中为1的一位
int first = 0; //记录第一个数
for(int x : nums){
if(x >> k & 1)
first ^= x;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20