Single Number I
Given an array of integers, every element appears twice except for one. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
分析
数组中只有一个数出现一次,其它都出现两次。我们知道一个数两次异或同一个数的结果是其本身:
x
参考代码
public class Solution {
public int singleNumber(int[] nums) {
int ret = 0;
for (int x : nums) ret ^= x;
return ret;
}
}
Single Number II
Given an array of integers, every element appears three times except for one. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
分析
每个数字出现三次,我们不能再简单地进行异或运算。这里我们从布尔代数的形式考虑。不管一个数大或小,它都是用二进制的比特位表示,每个比特位在布尔代数运算中相互独立,所以我们只考虑一个比特位。因为每个数出现三次,相当于一位比特位出现三次,它出现次数的状态有三种,初始为0,接下来依次为1、2,第三次清0,这样状态转移即为:00 -> 10 -> 01 -> 00。这是其中一种编码方式,我们需要两位二进制数来表示出现次数的状态,设为one,two。这样状态转移方程即为:
one = (one ^ x) & ~two
two = (two ^ x) & ~one
x表示当前的二进制比特位,0或1,状态的one不断被翻转,当上一次状态的two为1时,one变为0。状态的two位当下一个状态的one为0时才翻转。
关于状态转移的更多讨论点此查看。
参考代码
class Solution {
public:
int singleNumber(vector<int>& nums) {
int one = 0, two = 0;
for (int x : nums) {
one = (one ^ x) & ~ two;
two = (two ^ x) & ~ one;
}
return one;
}
};
Single Number III
Given an array of numbers nums
, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.
For example:
Given nums = [1, 2, 1, 3, 2, 5]
, return [3, 5]
.
Note:
- The order of the result is not important. So in the above example, [5, 3] is also correct.
- Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?
分析
每个数出现两次,可以和第一次一样用异或抵消,另外两个数各出现一次,最后的结果就是那两个数的异或。现在的问题是如何区分。我们知道如果两个不相等的数异或,一定有为1的比特位。比如
x
点此查看LeetCode上的详解
参考代码
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
vector<int> res(2, 0);
int n = 0;
for (int x : nums) n ^= x;
n &= -n;
for (int x : nums) res[!(x&n)] ^= x;
return res;
}
};