Single Number
Given a series of integers, each of the elements in the array appears times except one, you are asked to return that value.
When the problem is a quite simple one. As we know for any integer ,
and . So we XOR
all elements in the array, as every elements
that appears twice will product as the two operand of XOR
operator can be exchanged.
Then the results we be the same. This solutions is also correct when is even and
the only one item in the array appears odd times.
So what if is even? For the simplest case let's consider . In this case
we can not simply apply our XOR
all elements solution, but let's consider a single bit position i
and
the corresponding position in the number we want is 1
. If we count the number of 1
s appears at this position
through all elements, we will find it is a number that is not divisible by 3
. This conclusion comes from
the following observasions:
- The number to find has
1
at this position, so it gives 1 or 2 count - As for one of other numbers, if it has
1
at this position, as it appears three times, it always contributes 3 to the count. - If one of other numbers has
0
at this position, it won't change the result.
On the contrary, if the number to find has 0
at this position, the count of 1
s at that position
will be divisible by 3
too.
The simplest way to implement this is to use an array to count each position's 1
bits.
A better way is to use bit manipulation and turns it into a dyanamic programing like solution.
Let's say dp[i][0]
, dp[i][1]
and dp[i][2]
represents the states of elements from 0
to i
.
In dp[i][0]
's each bit position, if the number of 1
s appears there MOD
3 is 0
, then that
bit position is 1
. It is the same for the latter two variable. Then given i + 1
, it is obviously that
At last we can return ~dp[n][0]
.
To optimized the space use, we can just use 4 variable to implement this solution:
public class SingleNumber {
public int singleNumber(int[] nums) {
int mod0 = -1;
int mod1 = 0;
int mod2 = 0;
int t;
for (int n : nums) {
t = mod2;
mod2 = (mod1 & n) | (mod2 & ~n);
mod1 = (mod0 & n) | (mod1 & ~n);
mod0 = (t & n) | (mod0 & ~n);
}
return ~mod0;
}
}
Start from this, we can also write out general code for . There is a solution using less variables given in a discussion on LeetCode about this question.