website/content.en/ChapterFour/0100~0199/0137.Single-Number-II.md
Given a non-empty array of integers, every element appears three times except for one, which appears exactly once. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
Example 1:
Input: [2,2,3,2]
Output: 3
Example 2:
Input: [0,1,0,1,0,1,99]
Output: 99
Given a non-empty integer array, every element appears three times except for one element that appears only once. Find the element that appears only once. The algorithm is required to have linear time complexity and use no extra auxiliary space.
ternary (00, 01, 10).In golang, &^ means AND NOT. Here ^ as a unary operator means bitwise negation (^0001 0100 = 1110 1011). X &^ Y means keeping the bits in X that differ from Y and clearing the bits that are the same.
In golang, there is no ~ bit operation operator as in Java. The ~ operator in Java represents bitwise negation. This operation is equivalent to using the ^ operator in golang as a unary operator.
| (twos,ones) | xi | (twos'',ones') | ones' |
|---|---|---|---|
| 00 | 0 | 00 | 0 |
| 00 | 1 | 01 | 1 |
| 01 | 0 | 01 | 1 |
| 01 | 1 | 10 | 0 |
| 10 | 0 | 10 | 0 |
| 10 | 1 | 00 | 0 |
| (twos,ones') | xi | twos' |
|---|---|---|
| 00 | 0 | 0 |
| 01 | 1 | 0 |
| 01 | 0 | 0 |
| 00 | 1 | 1 |
| 10 | 0 | 1 |
| 10 | 1 | 0 |
This problem can also be further extended: in an array where every element appears 5 times, find the number that appears only once. How should this be done? The idea is still the same: simulate a base-5 system, and eliminate after 5 occurrences. The code is as follows:
// Solution 1
func singleNumberIII(nums []int) int {
na, nb, nc := 0, 0, 0
for i := 0; i < len(nums); i++ {
nb = nb ^ (nums[i] & na)
na = (na ^ nums[i]) & ^nc
nc = nc ^ (nums[i] & ^na & ^nb)
}
return na & ^nb & ^nc
}
// Solution 2
func singleNumberIIII(nums []int) int {
twos, threes, ones := 0xffffffff, 0xffffffff, 0
for i := 0; i < len(nums); i++ {
threes = threes ^ (nums[i] & twos)
twos = (twos ^ nums[i]) & ^ones
ones = ones ^ (nums[i] & ^twos & ^threes)
}
return ones
}
package leetcode
func singleNumberII(nums []int) int {
ones, twos := 0, 0
for i := 0; i < len(nums); i++ {
ones = (ones ^ nums[i]) & ^twos
twos = (twos ^ nums[i]) & ^ones
}
return ones
}
// The following is an extension problem
// In the array, every element appears 5 times; find the number that appears only once.
// Solution 1
func singleNumberIIIII(nums []int) int {
na, nb, nc := 0, 0, 0
for i := 0; i < len(nums); i++ {
nb = nb ^ (nums[i] & na)
na = (na ^ nums[i]) & ^nc
nc = nc ^ (nums[i] & ^na & ^nb)
}
return na & ^nb & ^nc
}
// Solution 2
func singleNumberIIIII1(nums []int) int {
twos, threes, ones := 0xffffffff, 0xffffffff, 0
for i := 0; i < len(nums); i++ {
threes = threes ^ (nums[i] & twos)
twos = (twos ^ nums[i]) & ^ones
ones = ones ^ (nums[i] & ^twos & ^threes)
}
return ones
}