NOTE
Numbers Appearing Only Once
Mirror translation of the original Sword Offer note: Numbers Appearing Only Once.
This is a historical learning note and may contain outdated or incomplete understanding.
1. Problem Description
In an integer array, every number appears twice except for two numbers. Write a program to find the two numbers that appear only once.
2. Approach
- Approach 1
- Map counting
- Approach 2
- XOR every element in the array. Since equal elements XOR to 0 and 0 XOR any number gives that number, the final result is the XOR of the two numbers that appear only once
- Take a bit whose value is 1 and AND it with every number in the array, dividing the array into one group whose result is nonzero and another whose result is zero
- XOR the two groups separately to obtain the two different numbers that appear once
3. Code
3.1. Map Counting
- java
public class 数组中只出现一次的数字
{
public static void main(String[] args)
{
new 数组中只出现一次的数字().FindNumsAppearOnce(new int[]{2, 4, 3, 6, 3, 2, 5, 5}, new int[]{0}, new int[]{0});
}
public void FindNumsAppearOnce(int[] array, int num1[], int num2[])
{
// Check parameters
if (array == null || array.length == 0)
{
num1[0] = 0;
num2[0] = 0;
return;
}
// XOR the array; the result must be the XOR of the two unique numbers
int xorResult = 0;
for (int val : array)
{
xorResult ^= val;
}
// From this result, select a bit whose value is 1
int bit = 1;
for (int i = 0; i < 32; i++)
{
if ((xorResult & bit) != 0)
{
break;
}
bit <<= 1;
}
// Traverse the array and AND each value with bit, dividing it into groups whose results are zero and nonzero
List<Integer> arrays1 = new LinkedList<>();
List<Integer> arrays2 = new LinkedList<>();
for (int val : array)
{
if ((val & bit) == 0)
{
arrays1.add(val);
}
else
{
arrays2.add(val);
}
}
// XOR the two groups separately to obtain the results
int n1 = 0;
for (Integer val : arrays1)
{
n1 ^= val;
}
int n2 = 0;
for (Integer val : arrays2)
{
n2 ^= val;
}
num1[0] = n1;
num2[0] = n2;
}
}
- go
// Time: O(N)
// Space: O(N)
func FindNumsAppearOnce(nums []int) []int {
count := make(map[int]int, 0)
for _, num := range nums {
count[num]++
}
res := make([]int, 0)
for _, num := range nums {
if count[num] == 1 {
res = append(res, num)
}
}
return res
}
3.2. XOR
// Time: O(N)
// Space: O(1)
func FindNumsAppearOnce2(nums []int) []int {
if len(nums) == 0 {
return nil
}
xorRes := 0
for _, num := range nums {
xorRes = xorRes ^ num
}
bit := 1
for i := 0; i < 32; i++ {
if xorRes&bit != 0 {
break
}
bit = bit << 1
}
val1 := 0
val2 := 0
for _, num := range nums {
if num&bit == 0 {
val1 = val1 ^ num
} else {
val2 = val2 ^ num
}
}
res := make([]int, 0)
res = append(res, val1)
res = append(res, val2)
return res
}
Discussion
Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub