Відповіді:
Ви знаєте, що , і томуS=n(n+1) можна кодувати вбітахO(log(n)),це можна зробити впам'ятіO(logn)і в одному шляху (просто знайдітьS-currentSum, це число відсутнє).
Але цю проблему можна було б вирішити в загальному випадку (для постійного ): ми маємо k пропущених чисел, з’ясуємо їх усі. У цьому випадку замість обчислення справедливої суми y i , обчисліть суму j'st потужності x i для всіх 1 ≤ j ≤ k (я припускав, що x i є відсутніми числами, а y i - вхідними числами):
Пам'ятайте , що ви можете вирахувати просто, тому що S 1 = S - ∑ y i , S 2 = ∑ i 2 - ∑ y 2 i , ...
Тепер для пошуку пропущених чисел слід вирішити щоб знайти всі x i .
Ви можете обчислити:
, P 2 = ∑ x i ⋅ x j , ..., P k = ∏ x i ( 2 ) .
Для цього пам’ятайте, що , P 2 = S 2 1 - S 2 , ...
Але - коефіцієнти P = ( x - x 1 ) ⋅ ( x - x 2 ) ⋯ ( x - x k ), але P можна враховувати однозначно, тому ви можете знайти пропущені числа.
Це не мої думки; читайте це .
From the comment above:
Before processing the stream, allocate bits, in which you write ( is the binary representation of and is pointwise exclusive-or). Naively, this takes time.
Upon processing the stream, whenever one reads a number , compute . Let be the single number from that is not included in the stream. After having read the whole stream, we have
Hence, we used space, and have an overall runtime of .
HdM's solution works. I coded it in C++ to test it. I can't limit the value
to bits, but I'm sure you can easily show how only that number of bits is actually set.
For those that want pseudo code, using a simple operation with exclusive or ():
Hand-wavey proof: A never requires more bits than its input, so it follows that no intermediate result in the above requires more than the maximum bits of the input (so bits). is commutative, and , thus if you expand the above and pair off all data present in the stream you'll be left only with a single un-matched value, the missing number.
#include <iostream>
#include <vector>
#include <cstdlib>
#include <algorithm>
using namespace std;
void find_missing( int const * stream, int len );
int main( int argc, char ** argv )
{
if( argc < 2 )
{
cerr << "Syntax: " << argv[0] << " N" << endl;
return 1;
}
int n = atoi( argv[1] );
//construct sequence
vector<int> seq;
for( int i=1; i <= n; ++i )
seq.push_back( i );
//remove a number and remember it
srand( unsigned(time(0)) );
int remove = (rand() % n) + 1;
seq.erase( seq.begin() + (remove - 1) );
cout << "Removed: " << remove << endl;
//give the stream a random order
std::random_shuffle( seq.begin(), seq.end() );
find_missing( &seq[0], int(seq.size()) );
}
//HdM's solution
void find_missing( int const * stream, int len )
{
//create initial value of n sequence xor'ed (n == len+1)
int value = 0;
for( int i=0; i < (len+1); ++i )
value = value ^ (i+1);
//xor all items in stream
for( int i=0; i < len; ++i, ++stream )
value = value ^ *stream;
//what's left is the missing number
cout << "Found: " << value << endl;
}