Description:
Given an array of N integers, such that each number in the array appears exactly twice, counter t for three numbers (say a, B and c) which appear exactly once.
In O (n) time and O (1) space find A, B and C.
Analysis:
Let's take a look at this question first:
There are only one and only one of the N numbers has an odd number (all other numbers have an even number). How can we find this number in a linear time constant space.
The solution is as follows:
The result is the required number. (The principle is clear)
Let's look at the enhanced version:
There are only two numbers in the number of n that appear odd (the other number appears even), how to use the linear time constant space to find this number.
The solution is clever. The main idea is to divide the elements into two groups. Each group contains only one and only one number has an odd number (the other number has an even number ), then apply the answer to the above questions. For how to group the questions, see:
1. xors for exclusive or all elements
2. Find a bit that is not 0 in xors (usually from right to left find the first bit that is not 0)
3. Use the bits found in 2 as sentinel and divide the array into two groups.
This question:
The idea is similar to solving the question. The key is to find the first question, and then use the conclusion of the question to find the other two
// Let S = a ^ B ^ C. We know that s not in (A, B, C ),
// Since if S = A, say, then B ^ c = 0 and B = C.
// Let f (x) be the lowest Bit where x differs from S.
// The algorithm computes flips = f (a) ^ F (B) ^ F (c ),
// Since the numbers appearing an even number of times cancel.
// The variable flips has parity 1, so it is non-zero,
// And lowbit (flips) is a bit where one or three of a, B, c
// Differ from S. It can't be three, however, so the final
// Exclusive-or already des exactly one of A, B, C.
Code:
# Include <iostream>
Using namespace STD;
// Get lowest different bit
Int lowbit (int x)
{
Return X &~ (X-1 );
}
// Given an array of N integers, such that each number
// In the array appears exactly twice, response t for two
// Numbers (say a and B) which appear exactly once.
//
// In O (n) time and O (1) Space find A and B.
// E.g.
// {2 3 3 2 4 6 4 7 8} ---> A/B = {6 7}
Void find2 (INT seq [], int N, Int & A, Int & B)
{
/// XOR
Int xors = 0;
For (INT I = 0; I <n; I ++)
Xors ^ = seq [I];
/// Get different bit
Int diff = lowbit (xors );
////
A = 0;
B = 0;
For (INT I = 0; I <n; I ++)
{
If (diff & seq [I])
A ^ = seq [I];
Else
B ^ = seq [I];
}
}
// Given an array of N integers, such that each number
// In the array appears exactly twice, response t for three
// Numbers (say a, B and c) which appear exactly once.
//
// In O (n) time and O (1) space find A, B and C.
// E.g.
// {2 3 3 2 4 6 4 7 8 8 1} ---> A/B = {6 7 1}
// Let S = a ^ B ^ C. We know that s not in (A, B, C ),
// Since if S = A, say, then B ^ c = 0 and B = C.
// Let f (x) be the lowest Bit where x differs from S.
// The algorithm computes flips = f (a) ^ F (B) ^ F (c ),
// Since the numbers appearing an even number of times cancel.
// The variable flips has parity 1, so it is non-zero,
// And lowbit (flips) is a bit where one or three of a, B, c
// Differ from S. It can't be three, however, so the final
// Exclusive-or already des exactly one of A, B, C.
Void find3 (INT seq [], int N, Int & A, Int & B, Int & C)
{
/// XOR
Int xors = 0;
For (INT I = 0; I <n; I ++)
Xors ^ = seq [I];
////
Int flips = 0;
For (INT I = 0; I <n; I ++)
Flips ^ = lowbit (xors ^ seq [I]);
Flips = lowbit (flips );
/// Get one of three
A = 0;
For (INT I = 0; I <n; I ++)
{
If (lowbit (SEQ [I] ^ xors) = flips)
A ^ = seq [I];
}
/// Swap a with the last element of seq
For (INT I = 0; I <n; I ++)
{
If (A = seq [I])
{
Int temp = seq [I];
SEQ [I] = seq [n-1];
SEQ [n-1] = temp;
}
}
/// Call find2 () to get B and C
Find2 (SEQ, n-1, B, c );
}
Int _ tmain (INT argc, _ tchar * argv [])
{
Int A, B, C;
Int test1 [] = {2, 3, 3, 2, 4, 6, 4, 7, 8 };
Find2 (test1, 10, A, B );
Cout <"A =" <A <", B =" <B <Endl;
Int Test2 [] = {1, 2, 3}; // {2, 3, 3, 2, 4, 6, 4, 7, 8, 8, 1 };
Find3 (Test2, 3, A, B, C );
Cout <"A =" <A <", B =" <B <", c =" <C <Endl;
System ("pause ");
Return 0;
}